package com.info.zhiduoduo.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.baomidou.mybatisplus.mapper.Condition;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.info.zhiduoduo.alipay.constant.AlipayIdentityEnum;
import com.info.zhiduoduo.alipay.constant.AlipayOrderEnum;
import com.info.zhiduoduo.alipay.constant.AlipayOrderStatusEnum;
import com.info.zhiduoduo.alipay.constant.AlipayPrincipalEnum;
import com.info.zhiduoduo.alipay.service.AliPayApiService;
import com.info.zhiduoduo.common.configs.CommonConfig;
import com.info.zhiduoduo.common.configs.PayConfig;
import com.info.zhiduoduo.common.configs.PayTestModeConfig;
import com.info.zhiduoduo.common.configs.ZddUrlConfig;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.constants.company.CompanyAccountFlowAccountType;
import com.info.zhiduoduo.common.constants.company.CompanyAccountFlowBizType;
import com.info.zhiduoduo.common.constants.company.CompanyPayType;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceProjectMatchState;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceProjectType;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceStepped;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceUserType;
import com.info.zhiduoduo.common.constants.maker.MakerType;
import com.info.zhiduoduo.common.constants.partner.BrokerageSettleType;
import com.info.zhiduoduo.common.constants.partner.PartnerBrokerageType;
import com.info.zhiduoduo.common.constants.pay.*;
import com.info.zhiduoduo.common.constants.project.CalcAmountType;
import com.info.zhiduoduo.common.constants.project.ProjectType;
import com.info.zhiduoduo.common.exception.Asserts;
import com.info.zhiduoduo.common.exception.RollbackException;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.formbean.BaseListFormBean;
import com.info.zhiduoduo.common.formbean.BaseSimpleFormBean;
import com.info.zhiduoduo.common.utils.DateUtil;
import com.info.zhiduoduo.common.utils.LogUtil;
import com.info.zhiduoduo.common.utils.MathUtils;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.RandomUtil;
import com.info.zhiduoduo.common.utils.StringUtil;
import com.info.zhiduoduo.core.dto.alipay.AlipayTransferFormBean;
import com.info.zhiduoduo.core.dto.alipay.AlipayTransferQueryFormBean;
import com.info.zhiduoduo.core.dto.dayspay.DaysAgentPayFormBean;
import com.info.zhiduoduo.core.dto.dayspay.DaysPayResDTO;
import com.info.zhiduoduo.core.dto.dayspay.DaysQueryAgentPayFormBean;
import com.info.zhiduoduo.core.dto.dayspay.DaysQueryPayResDTO;
import com.info.zhiduoduo.core.dto.pingan.*;
import com.info.zhiduoduo.core.dto.project.PayResultDto;
import com.info.zhiduoduo.core.dto.transferpay.BaseResDTO;
import com.info.zhiduoduo.core.dto.transferpay.TransferAgentPayFormBean;
import com.info.zhiduoduo.core.dto.transferpay.TransferPayResDTO;
import com.info.zhiduoduo.core.dto.transferpay.TransferQueryAgentPayFormBean;
import com.info.zhiduoduo.core.dto.transferpay.TransferQueryAgentPayResDTO;
import com.info.zhiduoduo.core.dto.zhaoshang.ZhaoShangAgentPayFormBean;
import com.info.zhiduoduo.core.dto.zhaoshang.ZhaoShangOutlineDTO;
import com.info.zhiduoduo.core.dto.zhaoshang.ZhaoShangPayDetailedDTO;
import com.info.zhiduoduo.core.dto.zhaoshang.ZhaoShangPayResDTO;
import com.info.zhiduoduo.core.dto.zhaoshang.ZhaoShangQueryPayDetailedFormBean;
import com.info.zhiduoduo.core.dto.zhaoshang.ZhaoShangTransactionOutlineFormBean;
import com.info.zhiduoduo.core.service.*;
import com.info.zhiduoduo.core.service.common.BaseService;
import com.info.zhiduoduo.repository.dto.account.BatchPayResultDto;
import com.info.zhiduoduo.repository.dto.account.BatchQueryResultDto;
import com.info.zhiduoduo.repository.dto.crowdsource.CalcCrowdsourceItemAmountModel;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceItemAmountCalcResult;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceProjectDetailDto;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceProjectItemDto;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceProjectItemModel;
import com.info.zhiduoduo.repository.dto.maker.MakerDetailDto;
import com.info.zhiduoduo.repository.dto.maker.StudioDetailDto;
import com.info.zhiduoduo.repository.dto.quota.CompanyQuotaDto;
import com.info.zhiduoduo.repository.dto.quota.MakerQuotaDto;
import com.info.zhiduoduo.repository.dto.quota.ZhiduoduoCityQuotaDto;
import com.info.zhiduoduo.repository.entity.company.*;
import com.info.zhiduoduo.repository.entity.crowdsource.*;
import com.info.zhiduoduo.repository.entity.invoice.Invoice;
import com.info.zhiduoduo.repository.entity.maker.*;
import com.info.zhiduoduo.repository.entity.partner.PartnerCompany;
import com.info.zhiduoduo.repository.entity.pay.Payment;
import com.info.zhiduoduo.repository.entity.pay.PaymentMerchant;
import com.info.zhiduoduo.repository.entity.quota.CityConfig;
import com.info.zhiduoduo.repository.entity.quota.CrowdsourceCityQuota;
import com.info.zhiduoduo.repository.entity.system.TaxSource;
import com.info.zhiduoduo.repository.mapper.company.CompanyAccountMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyPaymentMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyProjectMapper;
import com.info.zhiduoduo.repository.mapper.company.CrowdsourceMonthlyDepositRecordMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.*;
import com.info.zhiduoduo.repository.mapper.entrustmentproject.EntrustmentProjectItemMapper;
import com.info.zhiduoduo.repository.mapper.maker.MakerAlipayPrincipalOrderMapper;
import com.info.zhiduoduo.repository.mapper.maker.MakerMapper;
import com.info.zhiduoduo.repository.mapper.maker.MakerStudioMapper;
import com.info.zhiduoduo.repository.mapper.partner.PartnerBrokerageMapper;
import com.info.zhiduoduo.repository.mapper.partner.PartnerCompanyMapper;
import com.info.zhiduoduo.repository.mapper.partner.PartnerCrowdsourceSubMapper;
import com.info.zhiduoduo.repository.mapper.partner.PartnerMapper;
import com.info.zhiduoduo.repository.mapper.partner.PartnerSubMapper;
import com.info.zhiduoduo.repository.mapper.quota.CityConfigMapper;
import com.info.zhiduoduo.repository.mapper.quota.CompanyQuotaMapper;
import com.info.zhiduoduo.repository.mapper.quota.CrowdsourceCityQuotaMapper;
import com.info.zhiduoduo.repository.mapper.quota.MakerQuotaMapper;
import com.info.zhiduoduo.repository.mapper.quota.ZhiduoduoCityQuotaMapper;
import com.info.zhiduoduo.repository.mapper.taxer.TaxerInvoiceMapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class CrowdsourceProjectServiceImpl extends BaseService implements CrowdsourceProjectService {

	@Autowired
	MakerMapper makerMapper;
	@Autowired
	PartnerCompanyMapper partnerCompanyMapper;
	@Autowired
	PartnerBrokerageMapper partnerBrokerageMapper;
	@Autowired
	CompanyProjectMapper projectMapper;
	@Autowired
	CrowdsourceAccountMapper crowdsourceAccountMapper;
	@Autowired
	CrowdsourceProjectItemMapper crowdsourceProjectItemMapper;
	@Autowired
	CrowdsourceProjectMapper crowdsourceProjectMapper;
	@Autowired
	MakerStudioMapper makerStudioMapper;
	@Autowired
	TaxerInvoiceMapper taxerInvoiceMapper;
	@Autowired
	PartnerSubMapper partnerSubMapper;
	@Autowired
	PartnerMapper partnerMapper;
	@Resource
	PartnerCrowdsourceSubMapper partnerCrowdsourceSubMapper;
	@Autowired
	CrowdsourceTradeRecordMapper crowdsourceTradeRecordMapper;
	@Autowired
	CrowdsourceTradeRecordItemMapper crowdsourceTradeRecordItemMapper;
	@Resource
	CompanyAccountMapper companyAccountMapper;
	@Resource
	CompanyPaymentMapper companyPaymentMapper;
	@Resource
	CrowdsourceProjectMatchMapper crowdsourceProjectMatchMapper;
	@Resource
	CityConfigMapper cityConfigMapper;
	@Resource
	CrowdsourceCityQuotaMapper crowdsourceCityQuotaMapper;
	@Resource
	CrowdsourceMonthlyDepositRecordMapper crowdsourceMonthlyDepositRecordMapper;
	@Resource
	EntrustmentProjectItemMapper entrustmentProjectItemMapper;
	@Autowired
	CompanyQuotaMapper companyQuotaMapper;
	@Autowired
	MakerQuotaMapper makerQuotaMapper;
	@Autowired
	ZhiduoduoCityQuotaMapper zhiduoduoCityQuotaMapper;
	@Resource
	MakerAlipayPrincipalOrderMapper makerAlipayPrincipalOrderMapper;

	@Autowired
	CoreCompanyService coreCompanyService;
	@Autowired
	DingdingNoticeService dingdingNoticeService;
	@Autowired
	WxMessageService wxMessageService;
	@Autowired
	WxPartnerMessageService wxPartnerMessageService;
	@Autowired
	WxCrowdsourceMessageService wxCrowdsourceMessageService;
	@Autowired
	CeoNoticeService ceoNoticeService;
	@Autowired
	CoreProjectService coreProjectService;
	@Autowired
	CoreBrokerageService coreBrokerageService;
	@Autowired
	CoreInvoiceService coreInvoiceService;
	@Autowired
	CoreMakerAlipayService coreMakerAlipayService;
	@Autowired
	AliPayApiService aliPayApiService;
	@Autowired
	CoreOddJobService coreOddJobService;

	@Autowired
	CommonConfig commonConfig;
	@Autowired
	ZddUrlConfig zddUrlConfig;
	@Autowired
	PayConfig payConfig;
	@Autowired
	PayTestModeConfig payTestModeConfig;

	/**
	 * 刷新智众包项目，更新项目item明细，计算汇总数据，并返回最新的项目详情dto
	 */
	@Override
	public CrowdsourceProjectDetailDto refreshProjectDetail(CrowdsourceProject project) {
		int projectid = project.getProjectid();
		//获取全部项目明细，并更新项目汇总数据
		List<CrowdsourceProjectItemDto> itemList = crowdsourceProjectItemMapper.getItemList(projectid);

		BigDecimal projectTotalAmount = BigDecimal.ZERO;
		BigDecimal projectTotalServiceCharge = BigDecimal.ZERO;
		BigDecimal projectTotalPayableAmount = BigDecimal.ZERO;
		BigDecimal projectTotalBrokerage = BigDecimal.ZERO;
		BigDecimal projectTotalDepositAmount = BigDecimal.ZERO;
		BigDecimal projectTotalInvoiceAmount = BigDecimal.ZERO;

		for (CrowdsourceProjectItemDto itemDto : itemList) {
			projectTotalAmount = projectTotalAmount.add(itemDto.getProjectAmount());
			projectTotalServiceCharge = projectTotalServiceCharge.add(itemDto.getProjectServiceCharge());
			projectTotalPayableAmount = projectTotalPayableAmount.add(itemDto.getIntegratedTaxFee());
			projectTotalBrokerage = projectTotalBrokerage.add(itemDto.getPartnerBrokerage());
			projectTotalDepositAmount = projectTotalDepositAmount.add(itemDto.getDepositAmount());
		}
		//应付总金额+保证金
		projectTotalPayableAmount = projectTotalPayableAmount.add(projectTotalDepositAmount);
		//开票总金额
		projectTotalInvoiceAmount = projectTotalPayableAmount.subtract(projectTotalDepositAmount);

		project.setPeopleCount(itemList.size())
			   .setProjectTotalAmount(projectTotalAmount)
			   .setProjectTotalServiceCharge(projectTotalServiceCharge)
			   .setProjectTotalPayableAmount(projectTotalPayableAmount)
			   .setDepositTotalAmount(projectTotalDepositAmount)
			   .setProjectTotalInvoiceAmount(projectTotalInvoiceAmount)
			   .updateById();
		return crowdsourceProjectMapper.getDetail(projectid).setItemList(itemList);
	}

	@Override
	public SmartResult payCrowdsourceProject(CrowdsourceProject project, String companyInvoiceRemark) {
		if (project == null || project.getProjectid() == null) return smartResult(StatusMsg.StatusMsg_301);

		Integer compid = project.getCompid();
		Integer projectid = project.getProjectid();
		CompanyPayment companyPayment = companyPaymentMapper.getCompanyPayment(compid, project.getPayId());
		Asserts.notNullElseRollback(companyPayment, StatusMsg.StatusMsg_330.getMsg());

		CrowdsourceTradeRecord tradeRecord = new CrowdsourceTradeRecord().selectOne(Condition.create().eq("projectid", projectid));
		if (tradeRecord == null) {
			//还没有批量支付记录，创建批量记录和项目明细记录
			project.setState(Constants.CROWDSOURCE_PROJECT_PAYING).updateById();
			String tradeno = RandomUtil.createRandomNo("BTC_", "");
			//平安银行交易码小于20
			if (PayTypeSn.PA.equals(companyPayment.getPayTypeSn())) {
				tradeno = RandomUtil.createRandomNoForPingan("BTC_", "");
			}
			tradeRecord = new CrowdsourceTradeRecord().setBatchNo(tradeno)
					.setCompid(compid)
					.setProjectid(projectid)
					.setPayId(project.getPayId())
					.setMerchantid(companyPayment.getSourceId())
					.setTotalCount(project.getPeopleCount());
			if (tradeRecord.insert()) {
				BigDecimal beforeBalance = companyPayment.getBalance();
				BigDecimal currBalance = companyPayment.getBalance().subtract(project.getProjectTotalPayableAmount());

				//企业余额扣款
				companyPayment.setBalance(currBalance);

				if (companyPayment.updateById()) {
					//生成企业流水
					CompanyAccountflow accountflow = new CompanyAccountflow().setCompid(compid)
							.setBizid(projectid)
							.setBizType(project.getWorkType() == Constants.WORK_TYPE_1 ? CompanyAccountFlowBizType.CROWDSOURCE_PROJECT : CompanyAccountFlowBizType.CROWDSOURCE_ODD_PROJECT)
							.setFlowname(project.getWorkType() == Constants.WORK_TYPE_1 ? "智众包项目款" : "智零工项目款")
							.setFlowtype(2)
							.setFlowAmount(project.getProjectTotalPayableAmount())
							.setBeforeBalance(beforeBalance)
							.setCurrBalance(currBalance)
							.setBeforeFrozenBalance(companyPayment.getFrozenBalance())
							.setCurrFrozenBalance(companyPayment.getFrozenBalance())
							.setPayId(tradeRecord.getPayId());
					accountflow.insert();


					//企业账户扣款成功，创建发票
					Invoice invoice = coreInvoiceService.createCrowdsourceProjectInvoice(projectid);
					//发票含税金额不包含保证金，使用getProjectTotalInvoiceAmount字段
					invoice.setCompanyRemark(companyInvoiceRemark)
						   .setInvoiceAmount(project.getProjectTotalInvoiceAmount())
						   .setApplyInvoiceDate(project.getApplyInvoiceDate())
						   .updateById();
					Asserts.notNullElseRollback(invoice, StatusMsg.StatusMsg_221.getMsg());

					if (NumberUtil.equals(Constants.WORK_TYPE_2, project.getWorkType())) {
						//智零工项目 企业支付方式是平安银行冉澄/湖北辰双支付的生成智零工商户流水
						if(NumberUtil.intIn(companyPayment.getPayId(),CompanyPayType.PINGAN_TRANSFER_RANCHENG,CompanyPayType.PINGAN_CHENSHUANG)) {
							coreOddJobService.rechargeMerchantAndCreateFlowByProjected(project);
						}

						// 智零工类型需要生成到智零工发票表
						ContractorInvoice contractorInvoice = coreInvoiceService.createContractorInvoice(project.getProjectid());
						contractorInvoice.setCreatetime(project.getFinishtime());
						contractorInvoice.updateById();
					}

					int count = new Invoice().selectCount(Condition.create().eq("projectid", projectid).eq("project_type", 2));
					Asserts.isTrueElseRollback(count > 0, StatusMsg.StatusMsg_323.getMsg());

					//查询项目关联的自然人
					List<CrowdsourceProjectItem> itemList = new CrowdsourceProjectItem().selectList(
							Condition.create().eq("projectid", projectid).eq("deleted", 0));
					Asserts.notEmptyElseRollback(itemList, StatusMsg.StatusMsg_601.getMsg());

					//新建对应的自然人发票数据
					if (NumberUtil.equals(Constants.WORK_TYPE_1, project.getWorkType())) {
						itemList.forEach(item -> coreInvoiceService.createCrowdsourceProjectMakerInvoice(item.getId()));
					}
					return payCrowdsourceTradeInternal(tradeRecord);
				}
			}
		} else {
			//已存在，则判断是否可以提交支付
			Integer batchStatus = tradeRecord.getBatchStatus();
			Set<Integer> falledStatus = Sets.newHashSet(Constants.CROWDSOURE_BATCH_TRADE_VERIFY_FAILED,
					Constants.CROWDSOURE_BATCH_TRADE_BATCH_FAILED);
			Set<Integer> handlingStatus = Sets.newHashSet(Constants.CROWDSOURE_BATCH_TRADE_BATCH_HANDLING,
					Constants.CROWDSOURE_BATCH_TRADE_SUBMITTED, Constants.CROWDSOURE_BATCH_TRADE_SPLITTING,
					Constants.CROWDSOURE_BATCH_TRADE_SPLITTED);
			if (falledStatus.contains(batchStatus)) {
				//失败的，提示
				return smartResult(StatusMsg.StatusMsg_446);
			} else if (handlingStatus.contains(batchStatus)) {
				//状态不对，不能支付
				return smartResult(StatusMsg.StatusMsg_448);
			} else if (batchStatus == Constants.CROWDSOURE_BATCH_TRADE_BATCH_HANDLED ||
					batchStatus == Constants.CROWDSOURE_BATCH_TRADE_BATCH_FINISHED) {
				return smartResult(StatusMsg.StatusMsg_449);
			} else {
				return payCrowdsourceTradeInternal(tradeRecord);
			}
		}

		//到这里说明有未知的问题，导致报错，回滚
		throw new RollbackException(StatusMsg.StatusMsg_199.getMsg());
	}

	@Override
	public SmartResult repayCrowdsourceProjectItem(int itemid) {
		CrowdsourceProjectItem projectItem = new CrowdsourceProjectItem().selectById(itemid);
		if (projectItem == null) return smartResult(StatusMsg.StatusMsg_610);

		CrowdsourceProject project = new CrowdsourceProject().selectById(projectItem.getProjectid());
		if (project == null) return smartResult(StatusMsg.StatusMsg_301);

		CrowdsourceTradeRecordItem tradeRecordItem = new CrowdsourceTradeRecordItem().selectOne(
				Condition.create().eq("project_item_id", projectItem.getId()).eq("repay", 0));
		if (tradeRecordItem == null) return smartResult(StatusMsg.StatusMsg_444);

		CrowdsourceTradeRecord tradeRecord = new CrowdsourceTradeRecord().selectById(tradeRecordItem.getBatchId());
		if (tradeRecord == null) return smartResult(StatusMsg.StatusMsg_444);

		CompanyPayment companyPayment = companyPaymentMapper.getCompanyPayment(project.getCompid(),project.getPayId());
		if (companyPayment == null) return smartResult(StatusMsg.StatusMsg_330);

		//判断支付状态，是支付失败的才能重新支付
		Integer status = tradeRecordItem.getStatus();
		if (status == Constants.CROWDSOURCE_BATCH_ITEM_CREATED || status == Constants.CROWDSOURCE_BATCH_ITEM_PAYING) {
			return smartResult(StatusMsg.StatusMsg_448);
		} else if (status == Constants.CROWDSOURCE_BATCH_ITEM_PAID) {
			return smartResult(StatusMsg.StatusMsg_449);
		}

		//支付失败，重新创建单笔代付的支付。
		CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(tradeRecordItem.getProjectItemId());
		if (itemDto == null) {
			throw new RollbackException(StatusMsg.StatusMsg_606.getMsg());
		}
		MakerBankcard bankcard = new MakerBankcard().selectOne(
				Condition.create().eq("userid", itemDto.getUserid()).eq("state", 1).last("limit 1"));
		String acctno = itemDto.getAcctno();
		String bankname = itemDto.getBankname();
		String acctname = itemDto.getRealname();
		// 支付宝转账方式判断
		if (PayTypeSn.ZFB.equals(companyPayment.getPayTypeSn())) {
			if (StringUtil.isNotEmpty(bankcard.getAlipayAccount())) {
				acctno = bankcard.getAlipayAccount();
				bankname = "支付宝转账";
				acctname = bankcard.getPayername();
			} else {
				return SmartResult.fail(StatusMsg.StatusMsg_484);
			}
		}
		String tradeno = RandomUtil.createRandomNo("PAY_", "");
		//平安银行交易码小于20
		if (PayTypeSn.PA.equals(companyPayment.getPayTypeSn())) {
			tradeno = RandomUtil.createRandomNoForPingan("PAY_", "");
		}
		CrowdsourceTradeRecordItem newTradeItem = new CrowdsourceTradeRecordItem().setProjectid(tradeRecordItem.getProjectid())
				.setProjectItemId(tradeRecordItem.getProjectItemId())
				.setBatchId(tradeRecordItem.getBatchId())
				.setBatchNo(tradeRecordItem.getBatchNo())
				.setTradeNo(tradeno)
				.setAccttype(Constants.BANK_ACCT_TYPE_PERSONAL)
				.setAcctno(acctno)
				.setAcctname(acctname)
				.setBankname(bankname)
				.setTradeamount(tradeRecordItem.getTradeamount())
				.setPurpose("单笔重新支付")
				.setPayType(2)
				.setTradetime(new Date());
		if (tradeRecordItem.setRepay(1).updateById() && newTradeItem.insert()) {
			Integer payId = tradeRecord.getPayId();
			Payment payment = new Payment().selectById(payId);
			if (payment == null) {
				throw new RollbackException(StatusMsg.StatusMsg_330.getMsg());
			}
			if (payment.getSourceTable() == 1) {
				// 银行商户支付
				if (PayTypeSn.ZS.equals(payment.getPayTypeSn())) {
					return doCallZhaoShangRepayApi(tradeRecord, newTradeItem, project.getWorkType());
				} else if (PayTypeSn.PA.equals(payment.getPayTypeSn())) {
					return doCallPinganRePayApi(tradeRecord, newTradeItem, project.getWorkType());
				}
			} else if (payment.getSourceTable() == 2) {
				// 支付宝商户支付
				doCallPrincipalAliPayApi(tradeRecord, newTradeItem, companyPayment);
				return handleAliPayTransferPayResult(tradeRecord.getMerchantid(), newTradeItem);
			}

		}

		return smartResult(StatusMsg.StatusMsg_445);
	}

	@Override
	public void matchCrowdsourceProject() {
		List<CrowdsourceProjectMatch> list = crowdsourceProjectMatchMapper.listUnmatchedByCompid(0, 0);
		if (CollectionUtils.isEmpty(list)) return;
		for (CrowdsourceProjectMatch projectMatch : list) {
			list.stream()
					.filter(other -> !NumberUtil.equals(other.getCompid(), projectMatch.getCompid()) &&
							other.getState() == CrowdsourceProjectMatchState.CREATED)
					.min(Comparator.comparing(CrowdsourceProjectMatch::getCreatetime))
					.ifPresent(other -> {
						Date matchTime = new Date();
						projectMatch.setMatchCompid(other.getCompid())
								.setMatchProjectid(other.getProjectid())
								.setState(CrowdsourceProjectMatchState.MATCHED)
								.setMatchTime(matchTime);
						other.setMatchCompid(projectMatch.getCompid())
								.setMatchProjectid(projectMatch.getProjectid())
								.setState(CrowdsourceProjectMatchState.MATCHED)
								.setMatchTime(matchTime);
						projectMatch.updateById();
						other.updateById();
					});
		}
	}

	private SmartResult doCallZhaoShangRepayApi(CrowdsourceTradeRecord tradeRecord, CrowdsourceTradeRecordItem newTradeItem, Integer workType) {
		//调用第三方支付
		ZhaoShangAgentPayFormBean formBean = ZhaoShangAgentPayFormBean.of(newTradeItem, tradeRecord.getMerchantid(),workType);
		String url = zddUrlConfig.getBasePayUrl() + payConfig.getZhaoShangAgentPayUrl();
		LogUtil.info("支付调用 url = " + url);
		RestTemplate rest = new RestTemplate();
		SmartResult smartResult = rest.postForObject(url, formBean, SmartResult.class);
		handleZhaoShangPayResult(newTradeItem, smartResult);
		return smartResult;
	}

	private SmartResult doCallPinganRePayApi(CrowdsourceTradeRecord tradeRecord, CrowdsourceTradeRecordItem newTradeItem, Integer workType) {
		//调用第三方支付
		PinganTransferFormBean formBean = PinganTransferFormBean.of(newTradeItem, tradeRecord.getMerchantid(), workType);
		String url = zddUrlConfig.getBasePayUrl() + payConfig.getPinganSingleTransferUrl();
		LogUtil.info("支付调用 url = " + url);
		RestTemplate rest = new RestTemplate();
		SmartResult smartResult = rest.postForObject(url, formBean, SmartResult.class);
		return handlePinganPayResult(newTradeItem, smartResult);
	}

	/**
	 * 创建智众包项目的支付记录并发起支付请求
	 *
	 * @param tradeRecord
	 * @return
	 */
	private SmartResult payCrowdsourceTradeInternal(CrowdsourceTradeRecord tradeRecord) {
		Integer projectid = tradeRecord.getProjectid();
		List<CrowdsourceTradeRecordItem> tradeItemList = Lists.newArrayList();
		List<CrowdsourceProjectItemDto> itemList = crowdsourceProjectItemMapper.getItemList(projectid);

		CrowdsourceProject project = new CrowdsourceProject().setProjectid(projectid).selectById();
		Asserts.notNull(project,StatusMsg.StatusMsg_301);

		CompanyPayment companyPayment = companyPaymentMapper.getCompanyPayment(tradeRecord.getCompid(),tradeRecord.getPayId());
		Asserts.notNull(companyPayment,StatusMsg.StatusMsg_330);

		project.setState(Constants.CROWDSOURCE_PROJECT_PAYING).updateById();

		//平安银行批量支付
		for (CrowdsourceProjectItemDto itemDto : itemList) {
			MakerBankcard bankcard = new MakerBankcard().selectOne(
					Condition.create().eq("userid", itemDto.getUserid()).eq("state", 1).last("limit 1"));
			//2022.6.6 支付宝转账方式判断
			String acctno = itemDto.getAcctno();
			String bankname = itemDto.getBankname();
			String acctname = itemDto.getRealname();
			if (PayTypeSn.ZFB.equals(companyPayment.getPayTypeSn())) {
				if (StringUtil.isNotEmpty(bankcard.getAlipayAccount())) {
					acctno = bankcard.getAlipayAccount();
					acctname = bankcard.getPayername();
					bankname = "支付宝转账";
				} else {
					return SmartResult.fail(StatusMsg.StatusMsg_484);
				}
			}
			String tradeno = RandomUtil.createRandomNo("PAY_", "");
			//平安银行交易码小于20
			if (PayTypeSn.PA.equals(companyPayment.getPayTypeSn())) {
				tradeno = RandomUtil.createRandomNoForPingan("PAY_", "");
			}
			CrowdsourceTradeRecordItem tradeRecordItem = new CrowdsourceTradeRecordItem().setProjectid(projectid)
					.setProjectItemId(itemDto.getId())
					.setBatchId(tradeRecord.getBatchId())
					.setBatchNo(tradeRecord.getBatchNo())
					.setTradeNo(tradeno)
					.setAccttype(Constants.BANK_ACCT_TYPE_PERSONAL)
					.setAcctno(acctno)
					.setAcctname(acctname)
					.setBankname(bankname)
					.setTradeamount(itemDto.getProjectAmount())
					.setPurpose("批量支付单条明细")
					.setTradetime(new Date());
			//判断支付方式，企业如果选择的是九歌线下付款交易状态默认是交易中
			if (PayTypeSn.BTL.equals(companyPayment.getPayTypeSn())) {
				tradeRecordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
			}
			if (tradeRecordItem.insert()) {
				tradeItemList.add(tradeRecordItem);
			} else {
				throw new RollbackException("创建交易明细失败");
			}
		}


		//判断支付方式，企业如果选择的是非线下付款就不调用第三方支付接口
		if (!PayTypeSn.BTL.equals(companyPayment.getPayTypeSn())) {

			Integer payId = tradeRecord.getPayId();
			Payment payment = new Payment().selectById(payId);
			if (payment == null) {
				throw new RollbackException(StatusMsg.StatusMsg_330.getMsg());
			}
			if (payment.getSourceTable() == 1) {
				// 银行商户支付
				if (PayTypeSn.ZS.equals(payment.getPayTypeSn())) {
					doCallZhaoShangPayApi(tradeRecord, tradeItemList, project.getWorkType());
				} else if (PayTypeSn.PA.equals(payment.getPayTypeSn())) {
						doCallPinganPayApi(tradeRecord, tradeItemList, project.getWorkType());
				} else {
					throw new RollbackException(StatusMsg.StatusMsg_330.getMsg());
				}
			} else if (payment.getSourceTable() == 2) {
				// 支付宝商户支付
				tradeItemList.forEach(recordItem -> {
					doCallApiPaytransferApi(tradeRecord, recordItem);
				});
			}
		} else {
			tradeItemList.forEach(recordItem -> {
				//添加成功，发送模板消息给自然人
				CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
				wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);
			});
			//智众包项目选择的是九歌线下付款 给cindy发微信通知
			wxMessageService.notifyJiugeOfflineCrowdSourceProjectPaying(projectid);
		}
		return smartResult();
	}

	/**
	 * 处理智众包批量支付查询结果
	 */
	@Override
	public void handleCrowdsourceProjectTradeQueryResult(BatchQueryResultDto queryResult) {
		//更新批量交易记录
		CrowdsourceTradeRecord trade = new CrowdsourceTradeRecord().selectOne(
				Condition.create().eq("batch_no", queryResult.getMchtBatchNo()));
		if (trade == null) {
			LogUtil.info("查询批量代付结果，没有找到批量交易记录：" + queryResult.getMchtBatchNo());
			return;
		}

		Integer batchStatus = StringUtil.toInt(queryResult.getBatchStatus());
		trade.setBatchStatus(batchStatus)
				.setTotalCount(queryResult.getTotalCount())
				.setTotalSuccCount(queryResult.getTotalSuccCount())
				.setTotalFailCount(queryResult.getTotalFailCount())
				.setTotalSuccAmount(BigDecimal.valueOf(queryResult.getTotalSuccAmount() / 100))
				.setTotalFailAmount(BigDecimal.valueOf(queryResult.getTotalFailAmount() / 100))
				.setResponseCode(queryResult.getResponseCode())
				.setResponseMsg(queryResult.getResponseMsg());

		if (!trade.updateById()) {
			return;
		}
		List<BatchQueryResultDto.AgentPayDatailInfo> infoList = queryResult.getAgentPayDatailInfos();
		if (!CollectionUtils.isEmpty(infoList)) {
			infoList.forEach(info -> {
				CrowdsourceTradeRecordItem item = new CrowdsourceTradeRecordItem().selectOne(
						Condition.create().eq("trade_no", info.getMchtOrderNo()).eq("repay", 0));

				if (item == null) {
					LogUtil.info("批量代付结果处理，代付明细没有找到，代付明细结果：" + JSON.toJSONString(info));
					return;
				}
				//更新明细
				Integer status = StringUtil.toInt(info.getStatus());
				item.setErrorCode(info.getErrorCode()).setErrorMsg(info.getErrorMsg());
				if (!item.getStatus().equals(status)) {
					//如果当前状态与新状态一致，说明是重复通知。可以忽略。只有状态更新了，才继续处理。
					// 订单状态(0：已创建，1：交易中 2：交易成功，3：交易失败，4：拒绝) (此字段用于判断业务执行状态)
					switch (status) {
						case Constants.CROWDSOURCE_BATCH_ITEM_CREATED:
							item.setStatus(status);
							break;
						case Constants.CROWDSOURCE_BATCH_ITEM_PAYING:
							item.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
							break;
						case Constants.CROWDSOURCE_BATCH_ITEM_PAID:
							if (item.getStatus() != Constants.CROWDSOURCE_BATCH_ITEM_PAID) {
								item.setStatus(status).setFinishtime(new Date());
								wxCrowdsourceMessageService.notifyCrowdsourceProjectTradeItemPaid(item);
							}
							break;
						case Constants.CROWDSOURCE_BATCH_ITEM_FAILED:
							item.setStatus(status).setFinishtime(new Date());
							wxCrowdsourceMessageService.notifyProjectPayFailed(item);
							wxMessageService.notifyCrowdsourcePayFailed(item);
							break;
						case Constants.CROWDSOURCE_BATCH_ITEM_REFUSED:
							item.setStatus(status).setFinishtime(new Date());
							wxMessageService.notifyCrowdsourcePayFailed(item);
							wxCrowdsourceMessageService.notifyProjectPayFailed(item);
							break;
						default:
							break;
					}
					item.updateById();
				}
			});
		}

		handleCrowdsourceProjectState(trade, batchStatus);
	}

	/**
	 * 处理智众包批量支付查询结果
	 */
	@Override
	public void handleCrowdsourceProjectTradeQueryResultForPingan(BatchTransferQuery batchTransferQuery, String batchNo) {
		//更新批量交易记录
		CrowdsourceTradeRecord trade = new CrowdsourceTradeRecord().selectOne(
				Condition.create().eq("batch_no", batchNo));
		if (trade == null) {
			LogUtil.info("查询批量代付结果，没有找到批量交易记录：" + batchNo);
			return;
		}
		Integer batchStatus = Constants.CROWDSOURE_BATCH_TRADE_BATCH_HANDLED;
		if (batchTransferQuery.getBatchSTT().equals(PinganPayOrderState.SUCCESS)) {
			batchStatus = Constants.CROWDSOURE_BATCH_TRADE_BATCH_FINISHED;
		} else if (batchTransferQuery.getBatchSTT().equals(PinganPayOrderState.FAIL)){
			batchStatus = Constants.CROWDSOURE_BATCH_TRADE_BATCH_FAILED;
		}
		trade.setBatchStatus(batchStatus)
				.setTotalCount(StringUtil.toInt(batchTransferQuery.getCTotalCts()))
				.setTotalSuccCount(StringUtil.toInt(batchTransferQuery.getSuccessCts()))
				.setTotalFailCount(StringUtil.toInt(batchTransferQuery.getFaildCts()))
				.setTotalSuccAmount(new BigDecimal(batchTransferQuery.getSuccessAmt()))
				.setTotalFailAmount(new BigDecimal(batchTransferQuery.getFaildAmt()))
				.setResponseCode(batchTransferQuery.getBatchSTT())
				.setResponseMsg(batchTransferQuery.getSubBatchSTT());

		if (!trade.updateById()) {
			return;
		}
		List<BatchTransferQueryList> infoList = batchTransferQuery.getList();
		if (!CollectionUtils.isEmpty(infoList)) {
			infoList.forEach(info -> {
				CrowdsourceTradeRecordItem item = new CrowdsourceTradeRecordItem().selectOne(
						Condition.create().eq("project_item_id", info.getSThirdVoucher()).eq("repay", 0));

				if (item == null) {
					LogUtil.info("批量代付结果处理，代付明细没有找到，代付明细结果：" + JSON.toJSONString(info));
					return;
				}
				//更新明细
				Integer status = Constants.CROWDSOURCE_BATCH_ITEM_PAYING;
				String errorMsg = "";
				if (info.getStt().equals(PinganPayOrderState.SUCCESS)) {
					status = Constants.CROWDSOURCE_BATCH_ITEM_PAID;
					errorMsg = info.getBackRem();
				} else if (info.getStt().equals(PinganPayOrderState.FAIL)){
					status = Constants.CROWDSOURCE_BATCH_ITEM_FAILED;
					errorMsg = info.getBackRem();
				}
				item.setErrorCode(info.getStt()).setErrorMsg(errorMsg);
				if (!item.getStatus().equals(status)) {
					//如果当前状态与新状态一致，说明是重复通知。可以忽略。只有状态更新了，才继续处理。
					// 订单状态(0：已创建，1：交易中 2：交易成功，3：交易失败，4：拒绝) (此字段用于判断业务执行状态)
					switch (status) {
						case Constants.CROWDSOURCE_BATCH_ITEM_PAID:
							if (item.getStatus() != Constants.CROWDSOURCE_BATCH_ITEM_PAID) {
								item.setStatus(status).setFinishtime(new Date());
								wxCrowdsourceMessageService.notifyCrowdsourceProjectTradeItemPaid(item);
							}
							break;
						case Constants.CROWDSOURCE_BATCH_ITEM_FAILED:
							item.setStatus(status).setFinishtime(new Date());
							wxCrowdsourceMessageService.notifyProjectPayFailed(item);
							wxMessageService.notifyCrowdsourcePayFailed(item);
							break;
						default:
							item.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
							break;
					}
					item.updateById();
				}
			});
		}

		handleCrowdsourceProjectState(trade, batchStatus);
	}
	@Override
	public void queryCrowdsourceProjectTradeItemPayState(int batchId) {
		/*
		 * 根据tradeid 获取所有的item. 然后遍历查询支付结果,处理结果.
		 * 然后处理整体traderecord数据
		 * */
		CrowdsourceTradeRecord tradeRecord = new CrowdsourceTradeRecord().selectById(batchId);
		CrowdsourceProject crowdsourceProject = new CrowdsourceProject().selectById(tradeRecord.getProjectid());
		if (crowdsourceProject == null) {
			log.info("查询众包项目批量支付状态失败, 项目不存在: {}", tradeRecord.getProjectid());
			return;
		}
		Integer payId = tradeRecord.getPayId();
		Payment payment = new Payment().selectById(payId);
		if(payment == null){
			log.info("查询众包项目批量支付状态失败, 项目ID:{},支付方式不存在: {}", tradeRecord.getProjectid(),payId);
			return;
		}
		// 招商银行支付
		if (PayTypeSn.ZS.equals(payment.getPayTypeSn())) {
			crowdsourceTradeRecordItemMapper.getPayingItemList(batchId).stream().forEach(tradeItem -> {
				ZhaoShangQueryPayDetailedFormBean formBean = ZhaoShangQueryPayDetailedFormBean.of(payment.getSourceId(), tradeItem.getPartnerOrderNo());
				SmartResult smartResult = new RestTemplate().postForObject(zddUrlConfig.getBasePayUrl() + payConfig.getZhaoShangQueryAgentPayUrl(), formBean, SmartResult.class);
				if (smartResult.getObject() != null && smartResult.isSuccessful()) {
					ZhaoShangPayDetailedDTO payResult = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), ZhaoShangPayDetailedDTO.class);
					String errormsg = "";
					if (StringUtil.isNotEmpty(payResult.getErrtxt())) {
						errormsg = payResult.getErrtxt();
					} else {
						errormsg = payResult.getErrdsp();
					}
					handleZhaoShangPayTradeItemState(tradeItem, payResult.getStscod(), payResult.getErrcod(), errormsg, tradeRecord.getMerchantid());
				}
			});

		}
		// 平安银行支付
		else if (PayTypeSn.PA.equals(payment.getPayTypeSn())) {
			crowdsourceTradeRecordItemMapper.getPayingItemList(batchId).stream().forEach(tradeItem -> {
				PinganTransferQueryFormBean formBean = PinganTransferQueryFormBean.of(tradeRecord.getMerchantid(), tradeItem.getPartnerOrderNo());
				SmartResult smartResult = new RestTemplate().postForObject(zddUrlConfig.getBasePayUrl() + payConfig.getPinganSingleTransferUrl(), formBean, SmartResult.class);
				if (smartResult.getObject() != null && smartResult.isSuccessful()) {
					SingleTransferQuery singleTransferQuery = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), SingleTransferQuery.class);
					String errormsg = "";
					if (StringUtil.isNotEmpty(singleTransferQuery.getStt())) {
						errormsg = singleTransferQuery.getBackRem();
					} else {
						errormsg = smartResult.getMsg();
					}
					handlePinganPayTradeItemState(tradeItem, singleTransferQuery.getStt(), smartResult.getMsg(), errormsg);
				}
			});

		}
		// 委托接单支付宝支付
		else if (PayTypeSn.ZFB_WTJD.equals(payment.getPayTypeSn())) {
			crowdsourceTradeRecordItemMapper.getPayingItemList(batchId).stream().forEach(tradeItem -> {
				ArrayList<Integer> processingStatus = Lists.newArrayList(AlipayOrderStatusEnum.CREATE.id, AlipayOrderStatusEnum.WAIT_PAY.id, AlipayOrderStatusEnum.DEALING.id);
				MakerAlipayPrincipalOrder order = makerAlipayPrincipalOrderMapper.findByOrderNo(tradeItem.getTradeNo());
				try {
					// 再次判断状态, 防止其他线程同时处理这个订单.
					if (processingStatus.contains(order.getState())) {

						AlipayFundTransCommonQueryResponse response = aliPayApiService.fundTransCommonQuery(AlipayOrderEnum.PRINCIPAL_TRANSFER_PUBLIC_BANK, order.getOrderNo(), coreMakerAlipayService.getISVPrincipal());
						// 处理查询结果
						coreMakerAlipayService.handlePrincipalOrderQueryResponse(order, response, coreMakerAlipayService::recordPrincipalPayFlow);
						handlePrincipalAliPayTradeItemState(tradeItem, response.getStatus(), response.getSubCode(), response.getSubMsg());
					}

				} catch (Exception e) {
					log.error("定时刷新委托人转账给受托人创客记账本的订单信息报错, orderNo={}", order.getOrderNo(), e);
				}
			});
		}
		// 支付宝支付
		else if (PayTypeSn.ZFB.equals(payment.getPayTypeSn())) {
			crowdsourceTradeRecordItemMapper.getPayingItemList(batchId).stream().forEach(tradeItem -> {
				handleAliPayTransferPayResult(payId, tradeItem);
			});
		}

		// 刷新整个总包项目的状态
		refreshCrowdsourceProjectState(tradeRecord, crowdsourceProject);
		refreshCrowdsourceTradeRecordStatus(tradeRecord, crowdsourceProject);
		tradeRecord.updateById();
		crowdsourceProject.updateById();
	}

	private SmartResult handleAliPayTransferPayResult(Integer merchantId, CrowdsourceTradeRecordItem tradeItem) {
		AlipayTransferQueryFormBean formBean = AlipayTransferQueryFormBean.of(merchantId, tradeItem.getPartnerOrderNo());
		SmartResult smartResult = new RestTemplate().postForObject(
				zddUrlConfig.getBasePayUrl() + payConfig.getAliPayTransferQueryUrl(), formBean, SmartResult.class);
		if (smartResult.getObject() != null && smartResult.isSuccessful()) {
			//支付接口调用成功,查看交易结果
			AlipayFundTransCommonQueryResponse payResult = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), new TypeReference<AlipayFundTransCommonQueryResponse>() {
			});

			tradeItem.setErrorCode(payResult.getCode()).setErrorMsg(payResult.getSubMsg());
			if (payResult.isSuccess()) {
				if (!NumberUtil.equals(tradeItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_PAID)) {
					doAfterCrowdsourceItemPaid(tradeItem);
				}
			} else {
				if (!NumberUtil.equals(tradeItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
					tradeItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
					wxCrowdsourceMessageService.notifyProjectPayFailed(tradeItem);
					wxMessageService.notifyCrowdsourcePayFailed(tradeItem);
				}
			}
			tradeItem.updateById();
		}
		return SmartResult.success();
	}

	private void refreshCrowdsourceTradeRecordStatus(CrowdsourceTradeRecord tradeRecord, CrowdsourceProject crowdsourceProject) {
		Integer state = crowdsourceProject.getState();
		switch (state) {
			case Constants.CROWDSOURCE_PROJECT_CREATE:
				tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_SUBMITTED);
				break;
			case Constants.CROWDSOURCE_PROJECT_PAYING:
			case Constants.CROWDSOURCE_PROJECT_PART_PAID:
				tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_BATCH_HANDLING);
				break;
			case Constants.CROWDSOURCE_PROJECT_ALL_PAID:
			case Constants.CROWDSOURCE_PROJECT_ALL_PAID_EX:
				tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_BATCH_FINISHED).setFinishtime(new Date());
				break;
			case Constants.CROWDSOURCE_PROJECT_FAILED:
			case Constants.CROWDSOURCE_PROJECT_CANCELLED:
				tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_BATCH_FAILED).setFinishtime(new Date());
				break;
			default:

				break;
		}
	}

	private void doCallDaysPayApi(CrowdsourceTradeRecord tradeRecord, List<CrowdsourceTradeRecordItem> tradeItemList) {
		int payId = tradeRecord.getPayId();
		for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
			try {
				//调用第三方支付
				DaysAgentPayFormBean formBean = DaysAgentPayFormBean.of(recordItem, tradeRecord.getMerchantid());
				RestTemplate rest = new RestTemplate();

				String url = zddUrlConfig.getBasePayUrl() + payConfig.getDaysAgentPayUrl();
				LogUtil.info("支付调用 url = " + url);

				SmartResult smartResult;
				if (payTestModeConfig.isTestMode()) {
					//测试支付
					DaysPayResDTO payResultDto = new DaysPayResDTO().setResponseCode("000000")
							.setResponseRemark("测试支付成功")
							.setOrderState(DaysPayOrderState.PAY_SUCCESSFUL);
					smartResult = SmartResult.success(payResultDto);
				} else {
					//正式调用
					smartResult = rest.postForObject(url, formBean, SmartResult.class);
				}

				handleDaysPayResult(recordItem, smartResult);
				//添加成功，发送模板消息给自然人
				CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
				wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);
			} catch (Exception e) {
				log.error("智众包项目,得仕支付单笔项目报错,RecordItemId={}", recordItem.getId(), e);
				handleDaysPayResult(recordItem, null);
			}
		}
	}

	private void handleDaysPayResult(CrowdsourceTradeRecordItem recordItem, SmartResult smartResult) {
		/*
		 * 得仕支付,是直接单独代付. 如果支付报错,不能直接回滚所有的item.只能单独再次重新支付.
		 * 但是,如果是银行卡信息错误导致的支付报错. 那么重新支付还是不能解决问题.
		 * */
		if (smartResult == null) smartResult = SmartResult.fail(StatusMsg.StatusMsg_445);
		if (smartResult.getObject() == null || smartResult.isFailed()) {
			handleDaysPayTradeItemState(recordItem, "", String.valueOf(smartResult.getState()), smartResult.getMsg());
		} else {
			//支付接口调用成功,保存返回信息。
			DaysPayResDTO payResult = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), DaysPayResDTO.class);
			handleDaysPayTradeItemState(recordItem, payResult.getOrderState(), payResult.getResponseCode(), payResult.getResponseRemark());
		}
	}

	public SmartResult handleDaysPayTradeItemState(CrowdsourceTradeRecordItem recordItem, String orderState, String errorcode,
	                                               String errormsg) {
		if (recordItem == null) return SmartResult.success(StatusMsg.StatusMsg_444);
		recordItem.setErrorMsg(errorcode).setErrorMsg(errormsg);

		switch (orderState) {
			case DaysPayOrderState.NOT_PAY:
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_CREATED);
				break;
			case DaysPayOrderState.HANDLING:
			case DaysPayOrderState.PRIMARY_VERIFIED:
			case DaysPayOrderState.SECONDARY_VERIFIED:
			case DaysPayOrderState.PAYING:
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
				break;
			case DaysPayOrderState.PAY_SUCCESSFUL:
				if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_PAID)) {
					doAfterCrowdsourceItemPaid(recordItem);
				}
				break;
			case DaysPayOrderState.PAY_FAILED:
				if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
					recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
					wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
					wxMessageService.notifyCrowdsourcePayFailed(recordItem);
				}
				break;
			case "":
			default:
				if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
					recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
					wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
					wxMessageService.notifyCrowdsourcePayFailed(recordItem);
				}
				break;
		}

		if (recordItem.updateById()) return SmartResult.success();
		return SmartResult.fail(StatusMsg.StatusMsg_445);
	}

	private void handleCrowdsourceProjectState(CrowdsourceTradeRecord trade, int batchStatus) {
		Integer projectid = trade.getProjectid();
		CrowdsourceProject project = new CrowdsourceProject().selectById(projectid);
		switch (batchStatus) {
			case 0://已提交
			case 2:// 2：拆分中
			case 3://3：已拆分
			case 5://5:处理中
			case 6://6:已处理
				//处理中
				project.setState(Constants.CROWDSOURCE_PROJECT_PAYING);
				break;
			case 1://1：开联通审核不通过
			case 4://4: 批次失败
				project.setState(Constants.CROWDSOURCE_PROJECT_FAILED);
				trade.setFinishtime(new Date());
				break;
			case 7://7：已回盘
				trade.setFinishtime(new Date());
				break;
			default:
				break;
		}

		refreshCrowdsourceProjectState(trade, project);
		project.updateById();
		trade.updateById();

	}

	/**
	 * 刷新智众包项目的整体支付情况,比如 成功多少条,失败多条,成功支付多少钱,失败支付多少钱等.
	 *
	 * @param tradeRecord
	 * @param project
	 */
	private void refreshCrowdsourceProjectState(CrowdsourceTradeRecord tradeRecord, CrowdsourceProject project) {
		List<CrowdsourceTradeRecordItem> itemList = new CrowdsourceTradeRecordItem().selectList(
				Condition.create().eq("projectid", tradeRecord.getProjectid()).eq("repay", 0));
		if (CollectionUtils.isEmpty(itemList)) return;

		int succCount = 0;
		int failCount = 0;
		BigDecimal succAmount = BigDecimal.ZERO;
		BigDecimal failAmount = BigDecimal.ZERO;
		for (CrowdsourceTradeRecordItem item : itemList) {
			Integer status = item.getStatus();
			if (status == Constants.CROWDSOURCE_BATCH_ITEM_PAID) {
				succCount++;
				succAmount = succAmount.add(item.getTradeamount());
			} else if (NumberUtil.intIn(status, Constants.CROWDSOURCE_BATCH_ITEM_FAILED, Constants.CROWDSOURCE_BATCH_ITEM_REFUSED)) {
				failCount++;
				failAmount = failAmount.add(item.getTradeamount());
			}
		}

		tradeRecord.setTotalSuccCount(succCount).setTotalSuccAmount(succAmount).setTotalFailCount(failCount).setTotalFailAmount(failAmount);

		if (succCount > itemList.size()) {
			project.setState(Constants.CROWDSOURCE_PROJECT_ALL_PAID_EX);
		} else if (succCount == itemList.size()) {
			project.setState(Constants.CROWDSOURCE_PROJECT_ALL_PAID).setFinishtime(new Date());
			handleCrowdsourceProjectMatch(project);
			coreBrokerageService.handleCrowdsourceProjectPartnerBrokerage(tradeRecord, project);
			//全部处理完成，通知开票
			if(project.getWorkType() == 2) {
				wxMessageService.notifyWorkerAfterOddJobSubmit(project.getProjectid());
			}
		} else if (succCount > 0) {
			project.setState(Constants.CROWDSOURCE_PROJECT_PART_PAID);
		} else {
			project.setState(Constants.CROWDSOURCE_PROJECT_PAYING);
		}
	}

	/**
	 * 如果是撮合类型的项目, 初始化撮合项目
	 *
	 * @param project
	 */
	private void handleCrowdsourceProjectMatch(CrowdsourceProject project) {
		if (project == null || project.getProjectType() == null || CrowdsourceProjectType.MATCH != project.getProjectType()) return;
		CrowdsourceProjectMatch projectMatch = crowdsourceProjectMatchMapper.getByProjectid(project.getProjectid());
		if (projectMatch != null) return;
		new CrowdsourceProjectMatch().setCompid(project.getCompid())
				.setProjectid(project.getProjectid())
				.setState(CrowdsourceProjectMatchState.CREATED)
				.insert();
	}

	/**
	 * 处理智众包批量支付中的单条重新支付的结果
	 *
	 * @param tradeItem
	 * @param orderState
	 * @param errorcode
	 * @param errormsg
	 */
	@Override
	public void handleCrowdsourceProjectItemRepayTradeState(CrowdsourceTradeRecordItem tradeItem, String orderState, String errorcode,
	                                                        String errormsg) {
		if (tradeItem == null) return;

		tradeItem.setErrorCode(errorcode).setErrorMsg(errormsg);

		switch (orderState) {
			case "CREATE":
				tradeItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_CREATED);
				break;
			case "IN_PROCESS":
				tradeItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
				break;
			case "SUCCESS":
				if (tradeItem.getStatus() != Constants.CROWDSOURCE_BATCH_ITEM_PAID) {
					doAfterCrowdsourceItemPaid(tradeItem);
					tradeItem.updateById();
					doAfterCrowdsourceItemRepaySucceeded(tradeItem);
				}
				break;
			case "FAIL":
				if (tradeItem.getStatus() != Constants.CROWDSOURCE_BATCH_ITEM_FAILED) {
					tradeItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date()).updateById();
					wxCrowdsourceMessageService.notifyProjectPayFailed(tradeItem);
					wxMessageService.notifyCrowdsourcePayFailed(tradeItem);
				}
				break;
			case "REFUSE":
				if (tradeItem.getStatus() != Constants.CROWDSOURCE_BATCH_ITEM_REFUSED) {
					tradeItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_REFUSED).setFinishtime(new Date()).updateById();
					wxCrowdsourceMessageService.notifyProjectPayFailed(tradeItem);
					wxMessageService.notifyCrowdsourcePayFailed(tradeItem);
				}
				break;
			default:
				break;
		}
	}

	/**
	 * 智众包单条重新支付成功
	 */
	public void doAfterCrowdsourceItemRepaySucceeded(CrowdsourceTradeRecordItem tradeItem) {
		CrowdsourceTradeRecord tradeRecord = new CrowdsourceTradeRecord().selectById(tradeItem.getBatchId());
		CrowdsourceProject project = new CrowdsourceProject().selectById(tradeRecord.getProjectid());
		refreshCrowdsourceProjectState(tradeRecord, project);
		tradeRecord.updateById();
		project.updateById();
	}

//	private CityConfig getCrowdsourceCityMerchant(int projectid) {
//		CrowdsourceProject project = new CrowdsourceProject().selectById(projectid);
//		if (project == null) return null;
//
//		Integer compid = project.getCompid();
//		Company company = new Company().selectById(compid);
//		return new CityConfig().selectById(company.getCrowdsourceCity());
//	}

	private void doCallTransferPayApi(CrowdsourceTradeRecord tradeRecord, List<CrowdsourceTradeRecordItem> tradeItemList) {
		for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
			try {
				//调用第三方支付
				TransferAgentPayFormBean formBean = TransferAgentPayFormBean.of(recordItem, tradeRecord.getMerchantid());
				String url = zddUrlConfig.getBasePayUrl() + payConfig.getTransferAgentPayUrl();
				LogUtil.info("支付调用 url = " + url);

				SmartResult smartResult;
				if (payTestModeConfig.isTestMode()) {
					// 测试,直接成功
					TransferPayResDTO payResDTO = new TransferPayResDTO();
					payResDTO.setStatus(TransferPayOrderState.SUCCESS);
					payResDTO.setBusinessrecordnumber("11111");
					payResDTO.setBusinessnumber("11111");

					BaseResDTO<TransferPayResDTO> payResult = new BaseResDTO<>();
					payResult.setResult("success");
					payResult.setCode("000");
					payResult.setMsg("测试支付成功");
					payResult.setData(payResDTO);
					smartResult = SmartResult.success(payResult);
				} else {
					// 正式调用
					smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
				}
				handleTransferPayResult(recordItem, smartResult);

				//添加成功，发送模板消息给自然人
				CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
				wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);
			} catch (RestClientException e) {
				log.error("智众包项目,传化支付单笔项目报错,RecordItemId={}", recordItem.getId(), e);
				handleTransferPayResult(recordItem, null);
			}
		}
	}

	private SmartResult handleTransferPayResult(CrowdsourceTradeRecordItem recordItem, SmartResult smartResult) {
		if (smartResult == null) smartResult = SmartResult.fail(StatusMsg.StatusMsg_445);
		if (smartResult.getObject() == null || smartResult.isFailed()) {
			return handleDaysPayTradeItemState(recordItem, "", String.valueOf(smartResult.getState()), smartResult.getMsg());
		} else {
			//支付接口调用成功,查看交易结果
			BaseResDTO<TransferPayResDTO> payResult = JSON.parseObject(JSON.toJSONString(smartResult.getObject()),
					new TypeReference<BaseResDTO<TransferPayResDTO>>() {
					});
			TransferPayResDTO resData = payResult.getData();
			if ("success".equals(payResult.getResult()) && resData != null) {
				recordItem.setPartnerOrderNo(resData.getBusinessrecordnumber());
				return handleTransferPayTradeItemState(recordItem, resData.getStatus(), payResult.getCode(), payResult.getMsg());
			} else {
				return handleTransferPayTradeItemState(recordItem, "", payResult.getCode(), payResult.getMsg());
			}

		}
	}

	public SmartResult handleTransferPayTradeItemState(CrowdsourceTradeRecordItem recordItem, String orderState, String errorcode,
	                                                   String errormsg) {
		if (recordItem == null) return SmartResult.success(StatusMsg.StatusMsg_444);
		recordItem.setErrorCode(errorcode).setErrorMsg(errormsg);
		// 失败/成功/已退票
		switch (orderState) {
			case TransferPayOrderState.HANDLING:
				recordItem.setStatus(Constants.TRADE_IN_PROCESS);
				break;
			case TransferPayOrderState.SUCCESS:
				if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_PAID)) {
					doAfterCrowdsourceItemPaid(recordItem);
				}
				break;
			case TransferPayOrderState.FAIL:
			case TransferPayOrderState.REFUND:
				if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
					recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
					wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
					wxMessageService.notifyCrowdsourcePayFailed(recordItem);
				}
				break;
			case "":
			default:
				if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
					recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
					wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
					wxMessageService.notifyCrowdsourcePayFailed(recordItem);
				}
				break;
		}

		if (recordItem.updateById()) return SmartResult.success();
		return SmartResult.fail(StatusMsg.StatusMsg_445);
	}

	private void doAfterCrowdsourceItemPaid(CrowdsourceTradeRecordItem recordItem) {
		recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAID).setFinishtime(new Date());
		Integer projectItemId = recordItem.getProjectItemId();
		CrowdsourceProjectItem crowdsourceProjectItem = new CrowdsourceProjectItem().selectById(projectItemId);
		Integer userid = crowdsourceProjectItem.getUserid();
		Integer userType = crowdsourceProjectItem.getUserType();

		// 回款通知 和 首次评价通知
		if (NumberUtil.equals(userType, CrowdsourceUserType.NATURAL_PERSON)) {
			wxCrowdsourceMessageService.notifyCrowdsourceEvaluate(projectItemId);
			wxCrowdsourceMessageService.notifyCrowdsourceProjectTradeItemPaid(recordItem);
		} else {
			Maker maker = new Maker().selectById(userid);
			Integer makerType = maker.getMakerType();
			if (NumberUtil.equals(makerType, MakerType.INTELL)) {
				wxMessageService.notifyMakerCrowdsourceProjectEvaluate(projectItemId);
				wxMessageService.notifyCrowdsourceProjectTradeItemPaid(recordItem);
			} else if (NumberUtil.equals(makerType, MakerType.CROWDSOURCE)) {
				wxCrowdsourceMessageService.notifyMakerEvaluate(projectItemId);
				wxCrowdsourceMessageService.notifyCrowdsourceMakerProjectTradeItemPaid(recordItem);
			}
			//生成智众包项目创客流水
			generalCrowdMakerAccountFlow(crowdsourceProjectItem, recordItem.getId());
		}
	}

	/**
	 * 生成智众包项目创客流水
	 */
	private void generalCrowdMakerAccountFlow(CrowdsourceProjectItem crowdsourceProjectItem, Integer tradeRecordItemId) {
		CrowdsourceProject crowdsourceProject = new CrowdsourceProject().selectById(crowdsourceProjectItem.getProjectid());
		if (crowdsourceProject != null) {
			new MakerAccountflow().setFlowAmount(crowdsourceProjectItem.getProjectAmount())
								  .setFlowname("收到" + crowdsourceProject.getProjectName() + "项目款")
								  .setFlowtype(1)
								  .setAmounttype(0)
								  .setProjectid(crowdsourceProjectItem.getProjectid())
								  .setProjectItemId(crowdsourceProjectItem.getId())
								  .setProjectType(ProjectType.CROWDSOURCE)
								  .setTradeid(tradeRecordItemId)
								  .setCompid(crowdsourceProject.getCompid())
								  .setUserid(crowdsourceProjectItem.getUserid())
								  .insert();
		}
	}

	private void doCallZhaoShangPayApi(CrowdsourceTradeRecord tradeRecord, List<CrowdsourceTradeRecordItem> tradeItemList, Integer workType) {
		for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
			try {
				//调用第三方支付
				ZhaoShangAgentPayFormBean formBean = ZhaoShangAgentPayFormBean.of(recordItem, tradeRecord.getMerchantid(), workType);
				String url = zddUrlConfig.getBasePayUrl() + payConfig.getZhaoShangAgentPayUrl();
				LogUtil.info("支付调用 url = " + url);
				SmartResult smartResult;
				if (payTestModeConfig.isTestMode()) {
					//测试默认使用招商给的测试账户
					// formBean.setAcctno("6214831150131511").setAcctname("吴极客");
					// smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
					ZhaoShangPayResDTO resDTO = new ZhaoShangPayResDTO().setReqnbr("0000000000");
					smartResult = SmartResult.success(resDTO);
					handleZhaoShangPayResult(recordItem, smartResult);
					// 处理单笔支付成功
					for (CrowdsourceTradeRecordItem item : tradeItemList) {
						handleZhaoShangPayTradeItemState(item, "S", "", "测试环境, 直接支付成功", null);
					}
				} else {
					//正式调用
					smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
					handleZhaoShangPayResult(recordItem, smartResult);
				}

				//添加成功，发送模板消息给自然人
				CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
				wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);
			} catch (RestClientException e) {
				log.error("智众包项目,招商支付单笔项目报错,RecordItemId={}", recordItem.getId(), e);
				handleZhaoShangPayResult(recordItem, null);
			}
		}
	}

	/**
	 * 平安银行批量转账
	 * @param tradeRecord
	 * @param tradeItemList
	 * @param workType
	 */
	private void doCallPinganPayApi(CrowdsourceTradeRecord tradeRecord, List<CrowdsourceTradeRecordItem> tradeItemList, Integer workType) {
		PinganBatchTransferFormBean formBean = new PinganBatchTransferFormBean();
		formBean.setPaymentMerchant(tradeRecord.getMerchantid());
		formBean.setTradeNo(tradeRecord.getBatchNo());
		formBean.setThirdVoucher(tradeRecord.getBatchNo());
		formBean.setTotalCts(String.valueOf(tradeItemList.size()));
		BigDecimal totalAmt = new BigDecimal(0);
		List<PinganTransferOne> transferList = new ArrayList<>();
		for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
			PinganTransferOne pinganTransferOne = new PinganTransferOne();
			pinganTransferOne.setItemTradeNo(String.valueOf(recordItem.getProjectItemId()));
			pinganTransferOne.setTranAmount(recordItem.getTradeamount());
			pinganTransferOne.setAcctno(recordItem.getAcctno());
			pinganTransferOne.setAcctname(recordItem.getAcctname());
			pinganTransferOne.setUnionFlag(recordItem.getBankname().contains("平安银行") ? Constants.UNION_FLAG_IN : Constants.UNION_FLAG_OUT);
			pinganTransferOne.setDescribe(Constants.WORK_TYPE_1 == workType ? "服务费" : "服务费");
			transferList.add(pinganTransferOne);
			totalAmt = totalAmt.add(recordItem.getTradeamount());
		}
		formBean.setTotalAmt(totalAmt);
		formBean.setTransferList(transferList);
		try {
			//平安银行批量转账
			String url = zddUrlConfig.getBasePayUrl() + payConfig.getPinganBatchTransferUrl();
			LogUtil.info("平安银行批量转账调用 url = " + url);
			SmartResult smartResult;
			//接口调用
			smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
			handlePinganBatchTransferResult(tradeRecord, tradeItemList, smartResult);
			for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
				//添加成功，发送模板消息给自然人
				CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
				wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);
			}
		} catch (RestClientException e) {
			log.error("智众包项目,平安银行批量转账报错,BatchNo={}", tradeRecord.getBatchNo(), e);
			handlePinganBatchTransferResult(tradeRecord, tradeItemList,null);
		}
	}

	private void doCallApiPaytransferApi(CrowdsourceTradeRecord tradeRecord, CrowdsourceTradeRecordItem recordItem) {
		try {
			//调用第三方支付
			AlipayTransferFormBean formBean = AlipayTransferFormBean.of(recordItem, tradeRecord.getMerchantid());
			String url = zddUrlConfig.getBasePayUrl() + payConfig.getAliPayTransferUrl();
			LogUtil.info("支付宝转账支付调用 url = " + url);
//				if (payTestModeConfig.isTestMode()) {
//					//测试默认使用招商给的测试账户
//					// formBean.setAcctno("6214831150131511").setAcctname("吴极客");
//					// smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
//					ZhaoShangPayResDTO resDTO = new ZhaoShangPayResDTO().setReqnbr("0000000000");
//					smartResult = SmartResult.success(resDTO);
//					handleZhaoShangPayResult(recordItem, smartResult);
//					// 处理单笔支付成功
//					for (CrowdsourceTradeRecordItem item : tradeItemList) {
//						handleZhaoShangPayTradeItemState(item, "S", "", "测试环境, 直接支付成功", null);
//					}
//				} else {
			//正式调用
			SmartResult smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
			handlePayUserTradeState(recordItem, smartResult);

			//添加成功，发送模板消息给自然人
			CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
			wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);
		} catch (RestClientException e) {
			log.error("智众包项目,支付宝支付单笔项目报错,RecordItemId={}", recordItem.getId(), e);
			handlePayUserTradeState(recordItem, null);
		}
	}

	private SmartResult handlePayUserTradeState(CrowdsourceTradeRecordItem recordItem, SmartResult smartResult) {
		if (smartResult == null) smartResult = SmartResult.fail(StatusMsg.StatusMsg_445);
		if (smartResult.getObject() != null && smartResult.isSuccessful()) {
			AlipayFundTransCommonQueryResponse payResult = JSON.parseObject(JSON.toJSONString(smartResult.getObject()),
					new TypeReference<AlipayFundTransCommonQueryResponse>() {
					});
			if (payResult.isSuccess()) {
				recordItem.setPartnerOrderNo(payResult.getOutBizNo());
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
				if (recordItem.updateById()) {
					return SmartResult.success();
				} else {
					return SmartResult.fail(StatusMsg.StatusMsg_445);
				}
			} else {
				return handleDaysPayTradeItemState(recordItem, "", String.valueOf(payResult.getCode()),
						payResult.getSubMsg());
			}
		}else {
			return handleDaysPayTradeItemState(recordItem, "", String.valueOf(smartResult.getState()), smartResult.getMsg());
		}
	}
	private SmartResult handleZhaoShangPayResult(CrowdsourceTradeRecordItem recordItem, SmartResult smartResult) {
		if (smartResult == null) smartResult = SmartResult.fail(StatusMsg.StatusMsg_445);
		if (smartResult.getObject() == null || smartResult.isFailed()) {
			return handleDaysPayTradeItemState(recordItem, "", String.valueOf(smartResult.getState()), smartResult.getMsg());
		} else {
			ZhaoShangPayResDTO resData = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), ZhaoShangPayResDTO.class);
			if (StringUtil.isEmpty(resData.getReqnbr())) {
				return handleDaysPayTradeItemState(recordItem, "", String.valueOf(StatusMsg.StatusMsg_469.getState()),
						StatusMsg.StatusMsg_469.getMsg());
			} else {
				recordItem.setPartnerOrderNo(resData.getReqnbr());
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
				if (recordItem.updateById()) {
					return SmartResult.success();
				} else {
					return SmartResult.fail(StatusMsg.StatusMsg_445);
				}
			}
		}
	}

	private SmartResult handlePinganPayResult(CrowdsourceTradeRecordItem recordItem, SmartResult smartResult) {
		if (smartResult == null) smartResult = SmartResult.fail(StatusMsg.StatusMsg_445);
		if (smartResult.getObject() == null || smartResult.isFailed()) {
			return handleDaysPayTradeItemState(recordItem, "", String.valueOf(smartResult.getState()), smartResult.getMsg());
		} else {
			SingleTransfer resData = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), SingleTransfer.class);
			if (StringUtil.isEmpty(resData.getStt()) || PinganPayOrderState.FAIL.equals(resData.getStt())) {
				return handleDaysPayTradeItemState(recordItem, "", String.valueOf(StatusMsg.StatusMsg_469.getState()),
						StatusMsg.StatusMsg_469.getMsg());
			} else {
				recordItem.setPartnerOrderNo(resData.getThirdVoucher());
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
				if (recordItem.updateById()) {
					return SmartResult.success();
				} else {
					return SmartResult.fail(StatusMsg.StatusMsg_445);
				}
			}
		}
	}
	private SmartResult handlePinganBatchTransferResult(CrowdsourceTradeRecord tradeRecord, List<CrowdsourceTradeRecordItem> tradeItemList, SmartResult smartResult) {
		if (smartResult == null) smartResult = SmartResult.fail(StatusMsg.StatusMsg_445);
		if (smartResult.getObject() == null || smartResult.isFailed()) {
			tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_BATCH_FAILED).setFinishtime(new Date());
//	        wxMessageService.notifyCrowdsourcePayFailed(recordItem);
		} else {
			BatchTransfer resData = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), BatchTransfer.class);
			if (StringUtil.isEmpty(resData.getThirdVoucher())) {
				tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_BATCH_FAILED).setFinishtime(new Date());
//            wxMessageService.notifyCrowdsourcePayFailed(recordItem);
			} else {
				tradeRecord.setBatchStatus(Constants.CROWDSOURE_BATCH_TRADE_SUBMITTED);
				for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
					recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
					if (recordItem.updateById()) {
						return SmartResult.success();
					} else {
						return SmartResult.fail(StatusMsg.StatusMsg_445);
					}
				}
				new CrowdsourceTradeRecordItem().selectById(tradeRecord.getBatchId());
			}
		}
		if (tradeRecord.updateById()) {
			return SmartResult.success();
		} else {
			return SmartResult.fail(StatusMsg.StatusMsg_445);
		}

	}
	public SmartResult handleZhaoShangPayTradeItemState(CrowdsourceTradeRecordItem recordItem, String orderState, String errorcode,
	                                                    String errormsg, Integer merchantId) {
		if (recordItem == null) return SmartResult.success(StatusMsg.StatusMsg_444);
		recordItem.setErrorCode(errorcode).setErrorMsg(errormsg);
		if (ZhaoShangPayOrderState.SUCCESS.equals(orderState)) {
			if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_PAID)) {
				doAfterCrowdsourceItemPaid(recordItem);
			}
		} else if (ZhaoShangPayOrderState.FAIL.equals(orderState)) {
			if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
				wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
				wxMessageService.notifyCrowdsourcePayFailed(recordItem);
			}
		} else {
			//判断交易时间是否过了10分钟,如果超过了10分钟查询交易概要
			long differTime = DateUtil.differMinute(DateUtil.DateToStr("yyyy-MM-dd HH:mm:ss", recordItem.getTradetime()),
					DateUtil.DateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
			if (10 < differTime) {
				ZhaoShangTransactionOutlineFormBean formBean = ZhaoShangTransactionOutlineFormBean.of(merchantId,
						DateUtil.DateToStr("yyyyMMdd", recordItem.getTradetime()), recordItem.getTradeNo());
				//查询交易概要
				SmartResult smartResult = new RestTemplate().postForObject(
						zddUrlConfig.getBasePayUrl() + payConfig.getZhaoShangQueryOutlineUrl(), formBean, SmartResult.class);
				if (smartResult.getObject() != null && smartResult.isSuccessful()) {
					ZhaoShangOutlineDTO outline = JSON.parseObject(JSON.toJSONString(smartResult.getObject()),
							new TypeReference<ZhaoShangOutlineDTO>() {
							});
					//判断是不是支付失败
					if ("F".equals(outline.getRtnflg())) {
						if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
							recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED)
									.setErrorMsg(outline.getErrdsp())
									.setFinishtime(new Date());
							//判断如果错误信息是A6A0587 - 账户透支，则不会给自然人发送信息
							if (StringUtil.isNotEmpty(outline.getErrdsp()) && outline.getErrdsp().contains("账户透支")) {
								wxMessageService.notifyCrowdsourcePayFailed(recordItem);
							} else {
								wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
								wxMessageService.notifyCrowdsourcePayFailed(recordItem);
							}
						}
					}
				}
			}
		}
		if (recordItem.updateById()) return SmartResult.success();
		return SmartResult.fail(StatusMsg.StatusMsg_445);
	}
	public SmartResult handlePinganPayTradeItemState(CrowdsourceTradeRecordItem recordItem, String orderState, String errorcode,
														String errormsg) {
		if (recordItem == null) return SmartResult.success(StatusMsg.StatusMsg_444);
		if (PinganPayOrderState.SUCCESS.equals(orderState)) {
			if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_PAID)) {
				doAfterCrowdsourceItemPaid(recordItem);
			}
			recordItem.setErrorCode(errorcode).setErrorMsg(errormsg);
		} else if (PinganPayOrderState.FAIL.equals(orderState)) {
			if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
				wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
				wxMessageService.notifyCrowdsourcePayFailed(recordItem);
			}
			recordItem.setErrorCode(errorcode).setErrorMsg(errormsg);
		}
		if (recordItem.updateById()) return SmartResult.success();
		return SmartResult.fail(StatusMsg.StatusMsg_445);
	}

	private void doCallPrincipalAliPayApi(CrowdsourceTradeRecord tradeRecord, List<CrowdsourceTradeRecordItem> tradeItemList,CompanyPayment companyPayment) {
		for (CrowdsourceTradeRecordItem recordItem : tradeItemList) {
			doCallPrincipalAliPayApi(tradeRecord, recordItem,companyPayment);
		}
	}

	private SmartResult doCallPrincipalAliPayApi(CrowdsourceTradeRecord tradeRecord, CrowdsourceTradeRecordItem recordItem,CompanyPayment companyPayment) {
		try {
			//调用第三方支付
			SmartResult smartResult;
			if (payTestModeConfig.isTestMode()) {
				//测试默认使用招商给的测试账户
				// formBean.setAcctno("6214831150131511").setAcctname("吴极客");
				// smartResult = new RestTemplate().postForObject(url, formBean, SmartResult.class);
				AlipayFundTransUniTransferResponse response = new AlipayFundTransUniTransferResponse();
				response.setOrderId("0000000000");
				response.setStatus(AlipayOrderStatusEnum.SUCCESS.code);
				response.setSubCode("0000");
				handlePrincipalAliPayResult(recordItem, response);
				// 处理单笔支付成功
				smartResult = handlePrincipalAliPayTradeItemState(recordItem, response.getStatus(), response.getSubCode(), "测试环境, 直接支付成功");

			} else {
				//正式调用
				MakerAlipayPrincipal makerAlipayPrincipal = new MakerAlipayPrincipal().selectById(companyPayment.getSourceId());
				if(makerAlipayPrincipal == null) throw SmartException.of(StatusMsg.StatusMsg_456);
				CrowdsourceProject project = new CrowdsourceProject().selectById(tradeRecord.getProjectid());

				//调用第三方支付
				AlipayFundTransUniTransferResponse response = coreMakerAlipayService.principalPay(recordItem.getTradeNo(),
						recordItem.getProjectItemId(), ProjectType.CROWDSOURCE, makerAlipayPrincipal.getId(), recordItem.getTradeamount(),
						project.getProjectName(), AlipayIdentityEnum.BANKCARD_ACCOUNT, recordItem.getAcctno(), recordItem.getAcctname(),
						null);

				// 支付请求完成, 处理后续业务
				smartResult = handlePrincipalAliPayResult(recordItem, response);
			}

			//添加成功，发送模板消息给自然人
			CrowdsourceProjectItemDto itemDto = crowdsourceProjectItemMapper.getItemDto(recordItem.getProjectItemId());
			wxCrowdsourceMessageService.notifyCrowdsourceProjectSubmitted(itemDto);

			return smartResult;
		} catch (Exception e) {
			log.error("智众包项目,招商支付单笔项目报错,RecordItemId={}", recordItem.getId(), e);
			return handleZhaoShangPayResult(recordItem, null);
		}
	}

	private SmartResult handlePrincipalAliPayResult(CrowdsourceTradeRecordItem recordItem, AlipayFundTransUniTransferResponse response) {
		if (null == response || !response.isSuccess()) {
			if (response != null) {
				recordItem.setErrorCode(response.getSubCode()).setErrorMsg(response.getSubMsg());
			}
			recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date()).updateById();
			wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
			wxMessageService.notifyCrowdsourcePayFailed(recordItem);
			return SmartResult.fail(StatusMsg.StatusMsg_445);
		} else {
			recordItem.setPartnerOrderNo(response.getOrderId());
			recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
			if (recordItem.updateById()) {
				return SmartResult.success();
			} else {
				return SmartResult.fail(StatusMsg.StatusMsg_445);
			}

		}
	}

	public SmartResult handlePrincipalAliPayTradeItemState(CrowdsourceTradeRecordItem recordItem, String orderState, String errorcode,
	                                                       String errormsg) {
		if (recordItem == null) return SmartResult.success(StatusMsg.StatusMsg_444);
		AlipayOrderStatusEnum statusEnum = AlipayOrderStatusEnum.findByCode(orderState);
		recordItem.setErrorCode(errorcode).setErrorMsg(errormsg);
		if (statusEnum == AlipayOrderStatusEnum.SUCCESS) {
			if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_PAID)) {
				doAfterCrowdsourceItemPaid(recordItem);
			}
		} else if (statusEnum == AlipayOrderStatusEnum.DEALING || statusEnum == AlipayOrderStatusEnum.WAIT_PAY) {
			recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_PAYING);
		} else {
			if (!NumberUtil.equals(recordItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
				recordItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED).setFinishtime(new Date());
				wxCrowdsourceMessageService.notifyProjectPayFailed(recordItem);
				wxMessageService.notifyCrowdsourcePayFailed(recordItem);
			}
		}
		if (recordItem.updateById()) return SmartResult.success();
		return SmartResult.fail(StatusMsg.StatusMsg_445);
	}

	/**
	 * 计算单笔项目的综合税费和服务费，合伙人佣金
	 *
	 * @param project 智众包项目
	 * @return
	 */
	@Override
	public CrowdsourceItemAmountCalcResult calcItemAmount(CrowdsourceProject project, CrowdsourceProjectItemModel item, Company company,
	                                                      int calcAmountType) {
		CalcCrowdsourceItemAmountModel model = CalcCrowdsourceItemAmountModel.of(project.getProjectid(), ProjectType.CROWDSOURCE,
				project.getPartnerBrokerageRate(), company, item, calcAmountType, project.getWorkType(), project.getCrowdsourceCity());
		return calcItemAmount(model);
	}

	/**
	 * 计算单笔项目的综合税费和服务费，合伙人佣金
	 *
	 * @param project 智众包项目
	 * @return
	 */
	@Override
	public CrowdsourceItemAmountCalcResult calcItemAmountRepeat(CrowdsourceProject project, CrowdsourceProjectItemModel item, Company company,
																int calcAmountType, BigDecimal currProjectAmount, BigDecimal currTaxFee) {
		CalcCrowdsourceItemAmountModel model = CalcCrowdsourceItemAmountModel.of(project.getProjectid(), ProjectType.CROWDSOURCE,
				project.getPartnerBrokerageRate(), company, item, calcAmountType, project.getWorkType(), project.getCrowdsourceCity());
		return calcItemAmountRepeat(currProjectAmount, currTaxFee, model);
	}

	/**
	 * 计算单笔项目的综合税费和服务费，合伙人佣金
	 * <p> 存在事务，就加入到事务中；不存在事务，就不创建自己的事务。
	 *
	 * @return
	 */
	public CrowdsourceItemAmountCalcResult calcItemAmount(CalcCrowdsourceItemAmountModel model) {
		int calcAmountType = model.getCalcAmountType();
		int compid = model.getCompid();
		int userid = model.getUserid();
		int userType = model.getUserType();
		Integer crowdsourceCity = model.getCrowdsourceCity();
		int projectid = model.getProjectid();
		int projectItemId = model.getProjectItemId();
		int projectType = model.getProjectType();
		BigDecimal projectAmount = model.getProjectAmount();
		int crowdsourceStepped = model.getCrowdsourceStepped();
		int depositFlag = model.getDepositFlag();
		double depositRate = model.getDepositRate();
		double baseTaxRate = model.getBaseTaxRate();
		double lowTaxRate = model.getLowTaxRate();
		double highTaxRate = model.getHighTaxRate();
		double partnerBrokerageRate = model.getPartnerBrokerageRate();

		String realname = "";
		String username = "";
		if (userType == CrowdsourceUserType.NATURAL_PERSON) {
			CrowdsourceAccount crowdsource = new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", userid));
			if (crowdsource != null) realname = username = crowdsource.getRealname();
		} else if (userType == CrowdsourceUserType.STUDIO) {
			MakerDetailDto userDetail = makerMapper.getUserDetail(userid);
			if (userDetail != null) {
				realname = userDetail.getRealname();
				username = userDetail.getUsername();
			}
		}

		BigDecimal taxFee;

		BigDecimal monthlyTotalProjectAmount = BigDecimal.ZERO;
		BigDecimal quarterlyTotalProjectAmount = BigDecimal.ZERO;
		BigDecimal yearlyTotalProjectAmount = BigDecimal.ZERO;
		String crowdsourceProjectStates = CalcAmountType.getCrowdsourceProjectStates(calcAmountType);
		String entrustProjectStates = CalcAmountType.getEntrustProjectStates(calcAmountType);
		if (userType == CrowdsourceUserType.NATURAL_PERSON) {
			// 自然人
			if (calcAmountType == CalcAmountType.ALL) {
				monthlyTotalProjectAmount = crowdsourceProjectItemMapper.getMonthTotalProjectAmount(userid, userType, crowdsourceCity, projectid, 0,
						0);
				quarterlyTotalProjectAmount = crowdsourceProjectItemMapper.getQuarterTotalProjectAmount(userid, userType, crowdsourceCity, projectid, 0, 0);
				yearlyTotalProjectAmount = crowdsourceProjectItemMapper.getYearlyTotalProjectAmount(userid, userType, crowdsourceCity, projectid, 0);
			} else {
				monthlyTotalProjectAmount = crowdsourceProjectItemMapper.getMonthlyTotalProjectAmountByStates(userid, userType, crowdsourceCity,
						projectid, crowdsourceProjectStates, 0, 0);
				quarterlyTotalProjectAmount = crowdsourceProjectItemMapper.getQuarterTotalProjectAmountByStates(userid, userType, crowdsourceCity, projectid,
						crowdsourceProjectStates, 0, 0);
				yearlyTotalProjectAmount = crowdsourceProjectItemMapper.getYearlyTotalProjectAmountByStates(userid, userType, crowdsourceCity, projectid,
						crowdsourceProjectStates, 0);
			}

		} else if (userType == CrowdsourceUserType.STUDIO) {
			// 创客工作室,统计总金额, 需要包含创客在 项目的发单金额, 这个金额只包含支付中/已支付的项目item
			monthlyTotalProjectAmount = coreProjectService.getUserMonthlyTotalAmount(userid, calcAmountType, projectid, projectType);
			quarterlyTotalProjectAmount = coreProjectService.getUserQuarterTotalAmount(userid, calcAmountType, projectid, projectType);
			yearlyTotalProjectAmount = coreProjectService.getUserYearlyTotalAmount(userid, calcAmountType, projectid, projectType);
		}

		//保证金金额
		BigDecimal depositAmount = BigDecimal.ZERO;
		if (depositFlag == 2) {
			depositAmount = projectAmount.multiply(BigDecimal.valueOf(depositRate)).setScale(2, RoundingMode.DOWN);
		}

		// 2020.6.26 计算规则变更,改成顺加, 且只有一档税费(包含了服务费和税费). 只需要算税费和合伙人佣金2个金额即可
		// 2020.12.27 增加了阶梯费率计算规则. 发单给自然人,还是按照之前的逻辑.
		// 2021.02.09 自然人也要算阶梯费率
		// 发单给创客时,判断:如果开启,则使用阶梯费率, 没有. 如果未开启,则使用原来的计算规则.
		double taxRate = 0;
		if (NumberUtil.equals(crowdsourceStepped, CrowdsourceStepped.ON)) {
			// 本月总项目发单金额
			BigDecimal totalProjectAmount;
			// 智众包项目发单金额
			int crowdsourceProjectid = ProjectType.CROWDSOURCE == projectType ? projectid : 0;
			if (calcAmountType == CalcAmountType.ALL) {
				totalProjectAmount = crowdsourceProjectItemMapper.monthlyTotalProjectAmount(userid, compid, userType,
						crowdsourceProjectid);
			} else {
				totalProjectAmount = crowdsourceProjectItemMapper.monthlyTotalProjectAmountByStates(userid, compid, userType, projectid,
						crowdsourceProjectStates);
			}
			// 创客团项目发单金额
			int entrustProjectItemId = ProjectType.MAKER_GROUPON_CROWDSOURCE == projectType ? projectItemId : 0;
			if (userType == CrowdsourceUserType.STUDIO) {
				BigDecimal entrustAmount = entrustmentProjectItemMapper.sumUserMonthTotalProjectAmountByStates(userid,
						entrustProjectItemId,
						entrustProjectStates, ProjectType.MAKER_GROUPON_CROWDSOURCE, 0, 0, 0);
				totalProjectAmount = totalProjectAmount.add(entrustAmount);
			}

			double monthAmount = totalProjectAmount.add(projectAmount).doubleValue();

			// 本月总已缴税费
			BigDecimal totalPaidTaxFee;
			// 智众包项目已缴税费
			if (calcAmountType == CalcAmountType.ALL) {
				totalPaidTaxFee = crowdsourceProjectItemMapper.monthlyTotalTaxFee(userid, compid, userType, crowdsourceProjectid);
			} else {
				totalPaidTaxFee = crowdsourceProjectItemMapper.monthlyTotalTaxFeeByStates(userid, compid, userType, projectid,
						crowdsourceProjectStates);
			}
			// 创客团项目税费
			if (userType == CrowdsourceUserType.STUDIO) {
				BigDecimal entrustAmount = entrustmentProjectItemMapper.sumUserMonthTaxFeeByStates(userid, entrustProjectItemId,
						entrustProjectStates, ProjectType.MAKER_GROUPON_CROWDSOURCE);
				totalPaidTaxFee = totalPaidTaxFee.add(entrustAmount);
			}
			// 当前税率
			if (monthAmount > commonConfig.getCrowdsourceHighAmount()) {
				// 第三当 10万以上
				taxRate = NumberUtil.safeDouble(highTaxRate);
			} else if (monthAmount > commonConfig.getCrowdsourceLowAmount()) {
				// 第二档 3万-10万
				taxRate = NumberUtil.safeDouble(lowTaxRate);
			} else {
				// 第一档 3万以下
				taxRate = NumberUtil.safeDouble(baseTaxRate);
			}
			// 应交税率 = 当前档位税率-保证金比例
			taxRate = MathUtils.sub(taxRate, depositRate);
			// 总应交税费
			BigDecimal totalPayableTaxFee = totalProjectAmount.add(projectAmount).multiply(BigDecimal.valueOf(taxRate));
			// 本次项目税费, 包含需要补缴的部分
			taxFee = totalPayableTaxFee.subtract(totalPaidTaxFee).setScale(2, RoundingMode.DOWN);
			// 处理特殊情况, 之前税率比较高, 比如9%, 后来改成了6%, 则发布的项目, 可能出现之前的项目缴的税已经超过了目前按6%计算的税, 导致利用补税的逻辑计算出来的税费低于了6%,
			// 必须保证每次的税费不得低于当前的税率6%, 如果有补税的情况,则可以多余6%.
			BigDecimal originTaxFee = projectAmount.multiply(BigDecimal.valueOf(taxRate)).setScale(2, RoundingMode.DOWN);
			if (taxFee.compareTo(originTaxFee) < 0) taxFee = originTaxFee;
		} else {
			taxRate = baseTaxRate;
			taxFee = projectAmount.multiply(BigDecimal.valueOf(taxRate)).setScale(2, RoundingMode.DOWN);
			//项目税费 = 综合税费用 - 保证金金额
			taxFee = taxFee.subtract(depositAmount).setScale(2, RoundingMode.DOWN);
		}

		BigDecimal integratedTaxFee = projectAmount.add(taxFee)/*.add(partnerBrokerage)*/;

		// 2021.3.2 计算的时候改成按交易流水计算佣金，也就是内扣方式，佣金=含税金额*比例,
		BigDecimal partnerBrokerage = integratedTaxFee.multiply(BigDecimal.valueOf(partnerBrokerageRate)).setScale(2, RoundingMode.DOWN);
		return new CrowdsourceItemAmountCalcResult().setProjectId(projectid)
				.setProjectItemId(projectItemId)
				.setProjectType(projectType)
				.setCalcAmountType(calcAmountType)
				.setUserid(userid)
				.setDepositAmount(depositAmount)
				.setUsername(username)
				.setRealname(realname)
				.setUserType(userType)
				.setProjectAmount(projectAmount)
				.setMakerProjectAmount(projectAmount)
				.setIntegratedTaxFee(integratedTaxFee)
				.setTaxRate(taxRate)
				.setProjectServiceCharge(taxFee)
				.setPartnerBrokerage(partnerBrokerage)
				.setMonthlyTotalProjectAmount(monthlyTotalProjectAmount.add(projectAmount))
				.setQuarterlyTotalProjectAmount(quarterlyTotalProjectAmount.add(projectAmount))
				.setYearlyTotalProjectAmount(yearlyTotalProjectAmount.add(projectAmount));
	}

	/**
	 * 计算单笔项目的综合税费和服务费，合伙人佣金
	 * <p> 存在事务，就加入到事务中；不存在事务，就不创建自己的事务。
	 *
	 * @return
	 */
	public CrowdsourceItemAmountCalcResult calcItemAmountRepeat(BigDecimal currProjectAmount,
																BigDecimal currTaxFee,
																CalcCrowdsourceItemAmountModel model) {
		int calcAmountType = model.getCalcAmountType();
		int compid = model.getCompid();
		int userid = model.getUserid();
		int userType = model.getUserType();
		Integer crowdsourceCity = model.getCrowdsourceCity();
		int projectid = model.getProjectid();
		int projectItemId = model.getProjectItemId();
		int projectType = model.getProjectType();
		BigDecimal projectAmount = model.getProjectAmount();
		int crowdsourceStepped = model.getCrowdsourceStepped();
		int depositFlag = model.getDepositFlag();
		double depositRate = model.getDepositRate();
		double baseTaxRate = model.getBaseTaxRate();
		double lowTaxRate = model.getLowTaxRate();
		double highTaxRate = model.getHighTaxRate();
		double partnerBrokerageRate = model.getPartnerBrokerageRate();

		String idno = "";
		String realname = "";
		String username = "";
		if (userType == CrowdsourceUserType.NATURAL_PERSON) {
			CrowdsourceAccount crowdsource = new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", userid));
			if (crowdsource != null) {
				realname = username = crowdsource.getRealname();
				idno = crowdsource.getIdno();
			}
		} else if (userType == CrowdsourceUserType.STUDIO) {
			MakerDetailDto userDetail = makerMapper.getUserDetail(userid);
			if (userDetail != null) {
				realname = userDetail.getRealname();
				username = userDetail.getUsername();
				idno = userDetail.getIdno();
			}
		}

		BigDecimal taxFee;

		BigDecimal monthlyTotalProjectAmount = currProjectAmount;
		BigDecimal quarterlyTotalProjectAmount = currProjectAmount;
		BigDecimal yearlyTotalProjectAmount = currProjectAmount;
		//当前用户身份证下(创客+自然人)的年度交易额
		BigDecimal userIdnoYearAmout = currProjectAmount.add(coreProjectService.getTotalAmountByUserIdno(idno, projectid, projectType, calcAmountType, 0));
		//当前用户身份证下(创客+自然人)的连续12个月交易额
		BigDecimal userIdnoTwelveMonthAmout = currProjectAmount.add(coreProjectService.getTotalAmountByUserIdno(idno, projectid, projectType, calcAmountType, 1));
		String crowdsourceProjectStates = CalcAmountType.getCrowdsourceProjectStates(calcAmountType);
		String entrustProjectStates = CalcAmountType.getEntrustProjectStates(calcAmountType);
		if (userType == CrowdsourceUserType.NATURAL_PERSON) {
			// 自然人
			if (calcAmountType == CalcAmountType.ALL) {
				monthlyTotalProjectAmount = monthlyTotalProjectAmount.add(crowdsourceProjectItemMapper.getMonthTotalProjectAmount(userid, userType, crowdsourceCity, projectid, 0, 0));
				quarterlyTotalProjectAmount = quarterlyTotalProjectAmount.add(crowdsourceProjectItemMapper.getQuarterTotalProjectAmount(userid, userType,crowdsourceCity, projectid, 0, 0));
				yearlyTotalProjectAmount = yearlyTotalProjectAmount.add(crowdsourceProjectItemMapper.getYearlyTotalProjectAmount(userid, userType,crowdsourceCity, projectid, 0));
			} else {
				monthlyTotalProjectAmount = monthlyTotalProjectAmount.add(crowdsourceProjectItemMapper.getMonthlyTotalProjectAmountByStates(userid, userType,crowdsourceCity, projectid, crowdsourceProjectStates, 0, 0));
				quarterlyTotalProjectAmount = quarterlyTotalProjectAmount.add(crowdsourceProjectItemMapper.getQuarterTotalProjectAmountByStates(userid, userType, crowdsourceCity, projectid, crowdsourceProjectStates, 0, 0));
				yearlyTotalProjectAmount = yearlyTotalProjectAmount.add(crowdsourceProjectItemMapper.getYearlyTotalProjectAmountByStates(userid, userType, crowdsourceCity, projectid, crowdsourceProjectStates, 0));
			}

		} else if (userType == CrowdsourceUserType.STUDIO) {
			// 创客工作室,统计总金额, 需要包含创客在 项目的发单金额, 这个金额只包含支付中/已支付的项目item
			monthlyTotalProjectAmount = monthlyTotalProjectAmount.add(coreProjectService.getUserMonthlyTotalAmount(userid, calcAmountType, projectid, projectType));
			quarterlyTotalProjectAmount = quarterlyTotalProjectAmount.add(coreProjectService.getUserQuarterTotalAmount(userid, calcAmountType, projectid, projectType));
			yearlyTotalProjectAmount = yearlyTotalProjectAmount.add(coreProjectService.getUserYearlyTotalAmount(userid, calcAmountType, projectid, projectType));
		}

		//保证金金额
		BigDecimal depositAmount = BigDecimal.ZERO;
		if (depositFlag == 2) {
			depositAmount = projectAmount.multiply(BigDecimal.valueOf(depositRate)).setScale(2, RoundingMode.DOWN);
		}

		// 2020.6.26 计算规则变更,改成顺加, 且只有一档税费(包含了服务费和税费). 只需要算税费和合伙人佣金2个金额即可
		// 2020.12.27 增加了阶梯费率计算规则. 发单给自然人,还是按照之前的逻辑.
		// 2021.02.09 自然人也要算阶梯费率
		// 发单给创客时,判断:如果开启,则使用阶梯费率, 没有. 如果未开启,则使用原来的计算规则.
		double taxRate = 0;
		if (NumberUtil.equals(crowdsourceStepped, CrowdsourceStepped.ON)) {
			// 本月总项目发单金额
			BigDecimal totalProjectAmount = currProjectAmount;
			// 智众包项目发单金额
			int crowdsourceProjectid = ProjectType.CROWDSOURCE == projectType ? projectid : 0;
			if (calcAmountType == CalcAmountType.ALL) {
				totalProjectAmount = totalProjectAmount.add(crowdsourceProjectItemMapper.monthlyTotalProjectAmount(userid, compid, userType, crowdsourceProjectid));
			} else {
				totalProjectAmount = totalProjectAmount.add(crowdsourceProjectItemMapper.monthlyTotalProjectAmountByStates(userid, compid, userType, projectid, crowdsourceProjectStates));
			}
			// 创客团项目发单金额
			int entrustProjectItemId = ProjectType.MAKER_GROUPON_CROWDSOURCE == projectType ? projectItemId : 0;
			if (userType == CrowdsourceUserType.STUDIO) {
				BigDecimal entrustAmount = entrustmentProjectItemMapper.sumUserMonthTotalProjectAmountByStates(userid,
						entrustProjectItemId, entrustProjectStates, ProjectType.MAKER_GROUPON_CROWDSOURCE, 0, 0, 0);
				totalProjectAmount = totalProjectAmount.add(entrustAmount);
			}

			double monthAmount = totalProjectAmount.add(projectAmount).doubleValue();

			// 本月总已缴税费
			BigDecimal totalPaidTaxFee = currTaxFee;
			// 智众包项目已缴税费
			if (calcAmountType == CalcAmountType.ALL) {
				totalPaidTaxFee = totalPaidTaxFee.add(crowdsourceProjectItemMapper.monthlyTotalTaxFee(userid, compid, userType, crowdsourceProjectid));
			} else {
				totalPaidTaxFee = totalPaidTaxFee.add(crowdsourceProjectItemMapper.monthlyTotalTaxFeeByStates(userid, compid, userType, projectid, crowdsourceProjectStates));
			}
			// 创客团项目税费
			if (userType == CrowdsourceUserType.STUDIO) {
				BigDecimal entrustAmount = entrustmentProjectItemMapper.sumUserMonthTaxFeeByStates(userid, entrustProjectItemId,
						entrustProjectStates, ProjectType.MAKER_GROUPON_CROWDSOURCE);
				totalPaidTaxFee = totalPaidTaxFee.add(entrustAmount);
			}
			// 当前税率
			if (monthAmount > commonConfig.getCrowdsourceHighAmount()) {
				// 第三当 10万以上
				taxRate = NumberUtil.safeDouble(highTaxRate);
			} else if (monthAmount > commonConfig.getCrowdsourceLowAmount()) {
				// 第二档 3万-10万
				taxRate = NumberUtil.safeDouble(lowTaxRate);
			} else {
				// 第一档 3万以下
				taxRate = NumberUtil.safeDouble(baseTaxRate);
			}
			// 应交税率 = 当前档位税率-保证金比例
			taxRate = MathUtils.sub(taxRate, depositRate);
			// 总应交税费
			BigDecimal totalPayableTaxFee = totalProjectAmount.add(projectAmount).multiply(BigDecimal.valueOf(taxRate));
			// 本次项目税费, 包含需要补缴的部分
			taxFee = totalPayableTaxFee.subtract(totalPaidTaxFee).setScale(2, RoundingMode.DOWN);
			// 处理特殊情况, 之前税率比较高, 比如9%, 后来改成了6%, 则发布的项目, 可能出现之前的项目缴的税已经超过了目前按6%计算的税, 导致利用补税的逻辑计算出来的税费低于了6%,
			// 必须保证每次的税费不得低于当前的税率6%, 如果有补税的情况,则可以多余6%.
			BigDecimal originTaxFee = projectAmount.multiply(BigDecimal.valueOf(taxRate)).setScale(2, RoundingMode.DOWN);
			if (taxFee.compareTo(originTaxFee) < 0) taxFee = originTaxFee;
		} else {
			taxRate = baseTaxRate;
			taxFee = projectAmount.multiply(BigDecimal.valueOf(taxRate)).setScale(2, RoundingMode.DOWN);
			//项目税费 = 综合税费用 - 保证金金额
			taxFee = taxFee.subtract(depositAmount).setScale(2, RoundingMode.DOWN);
		}

		BigDecimal integratedTaxFee = projectAmount.add(taxFee)/*.add(partnerBrokerage)*/;

		// 2021.3.2 计算的时候改成按交易流水计算佣金，也就是内扣方式，佣金=含税金额*比例,
		BigDecimal partnerBrokerage = integratedTaxFee.multiply(BigDecimal.valueOf(partnerBrokerageRate)).setScale(2, RoundingMode.DOWN);
		return new CrowdsourceItemAmountCalcResult().setProjectId(projectid)
													.setProjectItemId(projectItemId)
													.setProjectType(projectType)
													.setCalcAmountType(calcAmountType)
													.setUserid(userid)
													.setDepositAmount(depositAmount)
													.setUsername(username)
													.setRealname(realname)
													.setUserType(userType)
													.setProjectAmount(projectAmount)
													.setIntegratedTaxFee(integratedTaxFee)
													.setTaxRate(taxRate)
													.setProjectServiceCharge(taxFee)
													.setPartnerBrokerage(partnerBrokerage)
													.setMakerProjectAmount(projectAmount.add(currProjectAmount))
													.setMonthlyTotalProjectAmount(monthlyTotalProjectAmount.add(projectAmount))
													.setQuarterlyTotalProjectAmount(quarterlyTotalProjectAmount.add(projectAmount))
													.setYearlyTotalProjectAmount(yearlyTotalProjectAmount.add(projectAmount))
													.setUserIdnoYearAmout(userIdnoYearAmout.add(projectAmount))
													.setUserIdnoTwelveMonthAmout(userIdnoTwelveMonthAmout.add(projectAmount));
	}

	@Override
	public void handleProjectItemCalcQuota(Company company, CrowdsourceItemAmountCalcResult itemAmountCalc,
	                                       CrowdsourceCityQuota personalQuota, CrowdsourceCityQuota studioQuota) {
		int userType = itemAmountCalc.getUserType();
		// 2021.9.25, 智众包项目：创客限额，包括创客团
		// 自然年500万，连续12个月480万
		// 企业>创客>创客注册地城市 2023-6-27——变更为：创客>企业>创客注册地城市
		if (userType == CrowdsourceUserType.STUDIO) {
			checkMakerQuota(company.getCompid(), itemAmountCalc);
		}

		// 企业和创客都没有超过限额，并且创客>企业的限额状态关闭，才检查众包城市限额 创客不需要检查众包城市注册地限额
		if (itemAmountCalc.getMakerExceedType() == 0 && itemAmountCalc.getMakerExceedPeriod() == 0 && userType == CrowdsourceUserType.NATURAL_PERSON) {
			if (itemAmountCalc.getMakerQuota() != null && NumberUtil.equals(itemAmountCalc.getMakerQuota().getQuotaFlag(), Constants.TRUE)) {
				return;
			} else if (itemAmountCalc.getCompanyQuota() != null && NumberUtil.equals(itemAmountCalc.getCompanyQuota().getQuotaFlag(), Constants.TRUE)) {
				return;
			}
			checkCrowdsourceCityQuota(company, itemAmountCalc, personalQuota, studioQuota, userType);

			// 个人所有业务年度限额 项目： 、智众包、纯代理、智零工、委托接单、创客团
			if(itemAmountCalc.getUserIdnoYearAmout().compareTo(commonConfig.getUserIdnoYearQuota()) > 0){
				itemAmountCalc.setMakerExceedType(5).setMakerExceedPeriod(2);
			}
			// 个人所有业务12个月限额
			if(itemAmountCalc.getUserIdnoTwelveMonthAmout().compareTo(commonConfig.getUserIdnoTwelveMonthQuota()) > 0){
				itemAmountCalc.setMakerExceedType(5).setMakerExceedPeriod(1);
			}
		}

	}

	private void checkCrowdsourceCityQuota(Company company, CrowdsourceItemAmountCalcResult itemAmountCalc,
	                                       CrowdsourceCityQuota personalQuota, CrowdsourceCityQuota studioQuota, int userType) {
		// 如果是创客工作室,则判断企业的阶梯费率是否开启,如果开启阶梯费率,则不需要检查单笔限额和月度限额.只需要检查年度限额
		boolean crowdsourceStepped = company.getCrowdsourceStepped() == CrowdsourceStepped.ON;
		// 计算限额
		//检查单个项目是否查过单笔限额
		double singleAmount = itemAmountCalc.getProjectAmount().doubleValue();
		double singleQuota = getSingleQuota(userType, personalQuota, studioQuota);
		boolean singleExceed = singleAmount > singleQuota;
		itemAmountCalc.setSingleExceed(singleExceed).setSingleQuota(BigDecimal.valueOf(singleQuota));
		// 单笔最大金额
		BigDecimal maxProjectAmount = BigDecimal.valueOf(singleQuota);
				// .subtract(itemAmountCalc.getPartnerBrokerage())
//				.subtract(itemAmountCalc.getProjectServiceCharge());
		itemAmountCalc.setMaxProjectAmount(maxProjectAmount);

		//检查自然人月度金额
		if (!crowdsourceStepped) {
			double monthlyAmount = itemAmountCalc.getMonthlyTotalProjectAmount().doubleValue();
			double monthlyQuota = getMonthlyQuota(userType, personalQuota, studioQuota);
			boolean monthlyExceed = monthlyAmount > monthlyQuota;
			itemAmountCalc.setMonthlyExceed(monthlyExceed).setMonthlyQuota(BigDecimal.valueOf(monthlyQuota));
		}

		//检查自然人季度金额
		double quarterlyAmount = itemAmountCalc.getQuarterlyTotalProjectAmount().doubleValue();
		double quarterlyQuota = getQuarterlyQuota(userType, personalQuota, studioQuota);
		boolean quarterlyExceed = quarterlyAmount > quarterlyQuota;
		itemAmountCalc.setQuarterlyExceed(quarterlyExceed).setQuarterlyQuota(BigDecimal.valueOf(quarterlyQuota));

		//检查自然人年度金额
		double yearlyAmount = itemAmountCalc.getYearlyTotalProjectAmount().doubleValue();
		double yearlyQuota = getYearlyQuota(userType, personalQuota, studioQuota);
		boolean yearlyExceed = yearlyAmount > yearlyQuota;
		itemAmountCalc.setYearlyExceed(yearlyExceed).setYearlyQuota(BigDecimal.valueOf(yearlyQuota));
	}

	private void checkMakerQuota(int compid, CrowdsourceItemAmountCalcResult itemAmountCalc) {
		int userid = itemAmountCalc.getUserid();
		int projectType = NumberUtil.safeInt(itemAmountCalc.getProjectType());
		// 企业限额
		CompanyQuotaDto companyQuota = companyQuotaMapper.getByCompid(compid);
		// 创客必须有效
		MakerDetailDto makerStudio = makerMapper.getUserDetail(userid);
		// 创客限额
		MakerQuotaDto makerQuota = makerQuotaMapper.getByUserid(userid);
		// 创客开户地城市限额
		ZhiduoduoCityQuotaDto cityQuota = zhiduoduoCityQuotaMapper.getByConfigId(makerStudio.getOpeningLocation());

		try {
			itemAmountCalc.setCompanyQuota(companyQuota).setMakerQuota(makerQuota).setCityQuota(cityQuota);
			coreProjectService.checkMakerQuota(compid, userid, itemAmountCalc.getProjectId(), projectType,
					itemAmountCalc.getProjectAmount(),itemAmountCalc.getMakerProjectAmount(), itemAmountCalc.getCalcAmountType(), false);
		} catch (SmartException e) {
			// 处理异常，根据报错状态码，设置
			int makerExceedType = 0;
			int makerExceedPeriod = 0;
			int state = e.getState();
			if (state == StatusMsg.StatusMsg_207.state) {
				makerExceedType = 1;
				makerExceedPeriod = 2;
			} else if (state == StatusMsg.StatusMsg_246.state) {
				makerExceedType = 2;
				makerExceedPeriod = 1;
			} else if (state == StatusMsg.StatusMsg_247.state) {
				makerExceedType = 2;
				makerExceedPeriod = 2;
			} else if (state == StatusMsg.StatusMsg_248.state) {
				makerExceedType = 3;
				makerExceedPeriod = 2;
			} else if (state == StatusMsg.StatusMsg_249.state) {
				makerExceedType = 4;
				makerExceedPeriod = 2;
			} else if (state == StatusMsg.StatusMsg_250.state) {
				makerExceedType = 2;
				makerExceedPeriod = 3;
			} else if (state == StatusMsg.StatusMsg_251.state) {
				makerExceedType = 3;
				makerExceedPeriod = 3;
			} else if (state == StatusMsg.StatusMsg_252.state) {
				makerExceedType = 4;
				makerExceedPeriod = 3;
			} else if (state == StatusMsg.StatusMsg_253.state) {
				makerExceedType = 2;
				makerExceedPeriod = 4;
			} else if (state == StatusMsg.StatusMsg_254.state) {
				makerExceedType = 3;
				makerExceedPeriod = 4;
			} else if (state == StatusMsg.StatusMsg_255.state) {
				makerExceedType = 4;
				makerExceedPeriod = 4;
			} else if (state == StatusMsg.StatusMsg_256.state) {
				makerExceedType = 2;
				makerExceedPeriod = 5;
			} else if (state == StatusMsg.StatusMsg_257.state) {
				makerExceedType = 3;
				makerExceedPeriod = 5;
			} else if (state == StatusMsg.StatusMsg_258.state) {
				makerExceedType = 4;
				makerExceedPeriod = 5;
			} else if (state == StatusMsg.StatusMsg_271.state) {
				makerExceedType = 5;
				makerExceedPeriod = 2;
			} else if (state == StatusMsg.StatusMsg_272.state) {
				makerExceedType = 5;
				makerExceedPeriod = 1;
			}
			itemAmountCalc.setMakerExceedType(makerExceedType).setMakerExceedPeriod(makerExceedPeriod);
		} catch (Exception e) {
			throw e;
		}
	}

	private double getSingleQuota(int userType, CrowdsourceCityQuota personalQuota, CrowdsourceCityQuota studioQuota) {
		if (userType == CrowdsourceUserType.NATURAL_PERSON && personalQuota != null) {
			return personalQuota.getCsOnceQuota().doubleValue();
		} else if (userType == CrowdsourceUserType.STUDIO && studioQuota != null) {
			return studioQuota.getCsOnceQuota().doubleValue();
		}
		return commonConfig.getCrowdsourceProjectItemQuota();
	}

	private double getMonthlyQuota(int userType, CrowdsourceCityQuota personalQuota, CrowdsourceCityQuota studioQuota) {
		if (userType == CrowdsourceUserType.NATURAL_PERSON && personalQuota != null) {
			return personalQuota.getCsMonthlyQuota().doubleValue();
		} else if (userType == CrowdsourceUserType.STUDIO && studioQuota != null) {
			return studioQuota.getCsMonthlyQuota().doubleValue();
		}
		return commonConfig.getCrowdsourceMonthlyQuota();
	}

	private double getQuarterlyQuota(int userType, CrowdsourceCityQuota personalQuota, CrowdsourceCityQuota studioQuota) {
		if (userType == CrowdsourceUserType.NATURAL_PERSON && personalQuota != null) {
			return personalQuota.getCsQuarterlyQuota().doubleValue();
		} else if (userType == CrowdsourceUserType.STUDIO && studioQuota != null) {
			return studioQuota.getCsQuarterlyQuota().doubleValue();
		}
		return commonConfig.getCrowdsourceQuarterlyQuota();
	}

	private double getYearlyQuota(int userType, CrowdsourceCityQuota personalQuota, CrowdsourceCityQuota studioQuota) {
		if (userType == CrowdsourceUserType.NATURAL_PERSON && personalQuota != null) {
			return personalQuota.getCsYearlyQuota().doubleValue();
		} else if (userType == CrowdsourceUserType.STUDIO && studioQuota != null) {
			return studioQuota.getCsYearlyQuota().doubleValue();
		}
		return commonConfig.getCrowdsourceYearlyQuota();
	}

	@Override
	public double getPartnerBrokerageRate(int compid) {
		return partnerCompanyMapper.getValidList(compid, PartnerBrokerageType.CROWDSOURCE).stream().filter(pc -> {
			// 过滤掉结算类型为 手动销账模式的
			return pc.getSettleType() != BrokerageSettleType.MANUAL;
		}).mapToDouble(PartnerCompany::getRatio).sum();
	}

	@Override
	public CrowdsourceCityQuota findPersonalCityQuota(int cityId) {
		return crowdsourceCityQuotaMapper.getByConfigIdAndUserType(cityId, CrowdsourceUserType.NATURAL_PERSON);
	}

	@Override
	public CrowdsourceCityQuota findStudioCityQuota(int userid) {
		CrowdsourceCityQuota studioQuota = null;
		StudioDetailDto studioDetail = makerStudioMapper.getStudioDetail(userid);
		if (studioDetail != null) {
			Integer openingLocation = studioDetail.getOpeningLocation();
			studioQuota = crowdsourceCityQuotaMapper.getByConfigIdAndUserType(openingLocation, CrowdsourceUserType.STUDIO);
		}
		return studioQuota;
	}

	//查询招商银行是否退票
	@Override
	public void queryZhaoShangPayTradeIsFail() {
		//查询最近两天所有交易成功的订单号 是否存在退票/ 如果交易失败则更新项目数据 并且 发送通知
		crowdsourceTradeRecordMapper.getSuccessTradeIds().forEach(batchId -> {
			try {
				CrowdsourceTradeRecord tradeRecord = new CrowdsourceTradeRecord().selectById(batchId);
				CrowdsourceProject crowdsourceProject = new CrowdsourceProject().selectById(tradeRecord.getProjectid());
				if (crowdsourceProject == null) {
					log.info("查询众包项目批量支付状态失败, 项目不存在: {}", tradeRecord.getProjectid());
					return;
				}

				crowdsourceTradeRecordItemMapper.getPayedItemList(batchId).stream().forEach(tradeItem -> {
					ZhaoShangQueryPayDetailedFormBean formBean = ZhaoShangQueryPayDetailedFormBean.of(tradeRecord.getMerchantid(), tradeItem.getPartnerOrderNo());
					SmartResult smartResult = new RestTemplate().postForObject(zddUrlConfig.getBasePayUrl() + payConfig.getZhaoShangQueryAgentPayUrl(), formBean, SmartResult.class);
					if (smartResult.getObject() != null && smartResult.isSuccessful()) {
						ZhaoShangPayDetailedDTO payResult = JSON.parseObject(JSON.toJSONString(smartResult.getObject()), ZhaoShangPayDetailedDTO.class);
						String errormsg = "";
						if (StringUtil.isNotEmpty(payResult.getErrtxt())) {
							errormsg = payResult.getErrtxt();
						} else {
							errormsg = payResult.getErrdsp();
						}
						//如果是失败状态，更新状态
						if (ZhaoShangPayOrderState.FAIL.equals(payResult.getStscod())) {
							if (!NumberUtil.equals(tradeItem.getStatus(), Constants.CROWDSOURCE_BATCH_ITEM_FAILED)) {
								tradeItem.setStatus(Constants.CROWDSOURCE_BATCH_ITEM_FAILED)
										 .setErrorCode(payResult.getErrcod())
										 .setErrorMsg(errormsg)
										 .setFinishtime(new Date())
										 .updateById();
								// 刷新整个众包项目的状态
								refreshCrowdsourceProjectState(tradeRecord, crowdsourceProject);
								refreshCrowdsourceTradeRecordStatus(tradeRecord, crowdsourceProject);
								tradeRecord.updateById();
								crowdsourceProject.updateById();
								// 发送通知
								wxCrowdsourceMessageService.notifyProjectPayFailed(tradeItem);
								wxMessageService.notifyCrowdsourcePayFailed(tradeItem);
							}
						}
					}
				});
			} catch (Exception e) {
				log.error("查询招商银行是否退票方法异常：", e);
			}
		});

	}

	/**
	 * 刷新项目中企业的最新信息-企业各项税率/支付方式/支付主体等
	 * @param projectId
	 * @return
	 */
	@Override
	public CrowdsourceProject getAndRefreshProject(int projectId) {
		CrowdsourceProject project = new CrowdsourceProject().selectById(projectId);
		Asserts.notNull(project,StatusMsg.StatusMsg_606);

		Integer compid = project.getCompid();
		Company company = new Company().selectById(compid);
		CompanyAccount companyAccount = companyAccountMapper.getByCompid(compid);
		Asserts.notNull(company,StatusMsg.StatusMsg_302);
		Asserts.notNull(companyAccount,StatusMsg.StatusMsg_302);

		Integer workType = project.getWorkType();
		// 获取企业默认支付方式
		CompanyParty companyParty = coreCompanyService.getCompanyDefaultPartyMul(compid,workType);
		Asserts.notNull(companyAccount,StatusMsg.StatusMsg_384);

		if(Constants.WORK_TYPE_2 == workType){
			// 智零工项目
			// 查询税源地
			TaxSource taxSource = new TaxSource().selectById(companyParty.getTaxSourceId());
			Asserts.notNull(taxSource,StatusMsg.StatusMsg_270);

			project.setBaseTaxRate(company.getBaseTaxRateOdd())
				   .setTaxSourceId(taxSource.getTaxSourceId())
				   .setTaxSourceCostRate(taxSource.getTaxSourceCostRate());
		} else {
			// 智众包项目
			project.setBaseTaxRate(company.getBaseTaxRate())
				   .setLowTaxRate(company.getLowTaxRate())
				   .setHighTaxRate(company.getHighTaxRate());
		}

		//获取企业众包项目的合伙人佣金比例
		double partnerBrokerageRate = getPartnerBrokerageRate(compid);

		// 开启保证金，需保存保证金比例
		Double depositRate = company.getDepositFlag() == 2 ? company.getDepositRate() : 0.0;
		project.setCompname(company.getCompname())
			   .setPayId(companyParty.getPayId())
			   .setPartyId(companyParty.getPartyId())
			   .setCrowdsourceCity(companyParty.getCityId())
			   .setDepositRate(depositRate)
			   .setProjectServiceRate(company.getProjectServiceRate())
			   .setPartnerBrokerageRate(partnerBrokerageRate)
			   .updateById();
		return project;
	}

}
